Merge "Fix tests that don't check composer's autoloader"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Thu, 22 Dec 2016 18:20:14 +0000 (18:20 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Thu, 22 Dec 2016 18:20:14 +0000 (18:20 +0000)
320 files changed:
RELEASE-NOTES-1.29
autoload.php
composer.json
docs/extension.schema.json [deleted file]
docs/extension.schema.v2.json [new file with mode: 0644]
docs/hooks.txt
includes/Block.php
includes/Category.php
includes/DefaultSettings.php
includes/EditPage.php
includes/GitInfo.php
includes/GlobalFunctions.php
includes/HistoryBlob.php
includes/Message.php
includes/OutputPage.php
includes/PathRouter.php
includes/Preferences.php
includes/PrefixSearch.php
includes/ProtectionForm.php
includes/Revision.php
includes/ServiceWiring.php
includes/SiteConfiguration.php
includes/Title.php
includes/WatchedItemStore.php
includes/WebRequest.php
includes/WikiMap.php
includes/actions/InfoAction.php
includes/api/ApiBase.php
includes/api/ApiEditPage.php
includes/api/ApiErrorFormatter.php
includes/api/ApiHelp.php
includes/api/ApiImport.php
includes/api/ApiMain.php
includes/api/ApiMessage.php
includes/api/ApiMove.php
includes/api/ApiPageSet.php
includes/api/ApiParamInfo.php
includes/api/ApiParse.php
includes/api/ApiQueryBase.php
includes/api/ApiQueryCategoryMembers.php
includes/api/ApiQueryImageInfo.php
includes/api/ApiQuerySearch.php
includes/api/ApiQueryStashImageInfo.php
includes/api/ApiQueryUserInfo.php
includes/api/ApiQueryWatchlist.php
includes/api/ApiStashEdit.php
includes/api/ApiTag.php
includes/api/ApiUpload.php
includes/api/ApiUsageException.php
includes/api/ApiValidatePassword.php [new file with mode: 0644]
includes/api/ApiWatch.php
includes/api/i18n/ar.json
includes/api/i18n/be-tarask.json
includes/api/i18n/bn.json
includes/api/i18n/cs.json
includes/api/i18n/de.json
includes/api/i18n/en.json
includes/api/i18n/es.json
includes/api/i18n/fr.json
includes/api/i18n/gl.json
includes/api/i18n/he.json
includes/api/i18n/it.json
includes/api/i18n/ko.json
includes/api/i18n/lb.json
includes/api/i18n/lt.json
includes/api/i18n/lv.json
includes/api/i18n/pl.json
includes/api/i18n/pt.json
includes/api/i18n/qqq.json
includes/api/i18n/ru.json
includes/api/i18n/sv.json
includes/api/i18n/udm.json
includes/api/i18n/uk.json
includes/api/i18n/zh-hans.json
includes/cache/FileCacheBase.php
includes/cache/MessageCache.php
includes/cache/localisation/LocalisationCache.php
includes/changes/CategoryMembershipChange.php
includes/collation/Collation.php
includes/collation/CollationFa.php [new file with mode: 0644]
includes/collation/IcuCollation.php
includes/content/Content.php
includes/content/WikitextContent.php
includes/db/CloneDatabase.php
includes/db/DatabaseMssql.php
includes/db/DatabaseOracle.php
includes/debug/MWDebug.php
includes/debug/logger/LegacyLogger.php
includes/diff/DairikiDiff.php
includes/diff/DifferenceEngine.php
includes/exception/ErrorPageError.php
includes/exception/LocalizedException.php [new file with mode: 0644]
includes/exception/MWExceptionHandler.php
includes/exception/MWExceptionRenderer.php
includes/exception/PermissionsError.php
includes/export/XmlDumpWriter.php
includes/externalstore/ExternalStoreDB.php
includes/filerepo/FSRepo.php [deleted file]
includes/filerepo/FileRepo.php
includes/filerepo/ForeignAPIRepo.php
includes/filerepo/RepoGroup.php
includes/filerepo/TempFileRepo.php [new file with mode: 0644]
includes/filerepo/file/ArchivedFile.php
includes/filerepo/file/File.php
includes/filerepo/file/ForeignDBFile.php
includes/filerepo/file/LocalFile.php
includes/htmlform/HTMLForm.php
includes/htmlform/HTMLFormField.php
includes/htmlform/OOUIHTMLForm.php
includes/htmlform/VFormHTMLForm.php
includes/htmlform/fields/HTMLButtonField.php
includes/htmlform/fields/HTMLFormFieldCloner.php
includes/htmlform/fields/HTMLMultiSelectField.php
includes/htmlform/fields/HTMLSizeFilterField.php
includes/http/Http.php
includes/installer/Installer.php
includes/installer/LocalSettingsGenerator.php
includes/installer/MssqlUpdater.php
includes/installer/MysqlUpdater.php
includes/installer/OracleUpdater.php
includes/installer/PostgresUpdater.php
includes/installer/SqliteUpdater.php
includes/installer/i18n/ar.json
includes/installer/i18n/es.json
includes/installer/i18n/fa.json
includes/installer/i18n/id.json
includes/installer/i18n/sd.json
includes/installer/i18n/tt-cyrl.json
includes/installer/i18n/zh-hant.json
includes/interwiki/ClassicInterwikiLookup.php
includes/jobqueue/JobRunner.php
includes/jobqueue/aggregator/JobQueueAggregatorRedis.php
includes/libs/ExplodeIterator.php
includes/libs/HashRing.php
includes/libs/StringUtils.php
includes/libs/filebackend/FileBackendStore.php
includes/libs/filebackend/SwiftFileBackend.php
includes/libs/lockmanager/LockManager.php
includes/libs/rdbms/database/DBConnRef.php
includes/libs/rdbms/database/Database.php
includes/libs/rdbms/database/DatabaseSqlite.php
includes/libs/rdbms/database/IMaintainableDatabase.php
includes/libs/rdbms/database/MaintainableDBConnRef.php [new file with mode: 0644]
includes/libs/rdbms/exception/DBExpectedError.php
includes/libs/rdbms/loadbalancer/ILoadBalancer.php
includes/libs/rdbms/loadbalancer/LoadBalancer.php
includes/libs/xmp/XMP.php
includes/logging/LogEntry.php
includes/mail/UserMailer.php
includes/page/WikiPage.php
includes/pager/TablePager.php
includes/parser/CoreParserFunctions.php
includes/parser/Parser.php
includes/parser/ParserOutput.php
includes/parser/Preprocessor.php
includes/parser/Preprocessor_DOM.php
includes/parser/Preprocessor_Hash.php
includes/password/ParameterizedPassword.php
includes/password/Password.php
includes/registration/CoreVersionChecker.php [deleted file]
includes/registration/ExtensionJsonValidator.php
includes/registration/ExtensionProcessor.php
includes/registration/ExtensionRegistry.php
includes/registration/VersionChecker.php [new file with mode: 0644]
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderClientHtml.php
includes/resourceloader/ResourceLoaderStartUpModule.php
includes/revisiondelete/RevDelArchivedFileItem.php
includes/revisiondelete/RevDelFileItem.php
includes/revisiondelete/RevDelLogItem.php
includes/revisiondelete/RevDelRevisionItem.php
includes/search/DummySearchIndexFieldDefinition.php
includes/search/SearchEngine.php
includes/skins/SkinTemplate.php
includes/specialpage/AuthManagerSpecialPage.php
includes/specials/SpecialDeletedContributions.php
includes/specials/SpecialMIMEsearch.php
includes/specials/SpecialMediaStatistics.php
includes/specials/SpecialNewimages.php
includes/specials/SpecialRecentchanges.php
includes/specials/SpecialRunJobs.php
includes/specials/SpecialUpload.php
includes/specials/SpecialUserrights.php
includes/title/MalformedTitleException.php
includes/upload/UploadBase.php
includes/upload/UploadFromChunks.php
includes/user/User.php
languages/Language.php
languages/LanguageConverter.php
languages/classes/LanguageHe.php [deleted file]
languages/classes/LanguageRu.php
languages/classes/LanguageUk.php
languages/data/grammarTransformations/he.json [new file with mode: 0644]
languages/data/grammarTransformations/uk.json [new file with mode: 0644]
languages/i18n/ar.json
languages/i18n/be-tarask.json
languages/i18n/be.json
languages/i18n/bn.json
languages/i18n/bqi.json
languages/i18n/ce.json
languages/i18n/ckb.json
languages/i18n/cs.json
languages/i18n/de.json
languages/i18n/diq.json
languages/i18n/en.json
languages/i18n/eo.json
languages/i18n/es.json
languages/i18n/et.json
languages/i18n/eu.json
languages/i18n/fa.json
languages/i18n/fi.json
languages/i18n/fo.json
languages/i18n/fr.json
languages/i18n/frr.json
languages/i18n/gl.json
languages/i18n/he.json
languages/i18n/hi.json
languages/i18n/hr.json
languages/i18n/hy.json
languages/i18n/ia.json
languages/i18n/id.json
languages/i18n/it.json
languages/i18n/jv.json
languages/i18n/ka.json
languages/i18n/ko.json
languages/i18n/lb.json
languages/i18n/lij.json
languages/i18n/lo.json
languages/i18n/lt.json
languages/i18n/lv.json
languages/i18n/mk.json
languages/i18n/my.json
languages/i18n/nah.json
languages/i18n/nb.json
languages/i18n/nl.json
languages/i18n/or.json
languages/i18n/pl.json
languages/i18n/pt-br.json
languages/i18n/pt.json
languages/i18n/qqq.json
languages/i18n/ro.json
languages/i18n/ru.json
languages/i18n/sah.json
languages/i18n/sd.json
languages/i18n/sl.json
languages/i18n/sv.json
languages/i18n/th.json
languages/i18n/tr.json
languages/i18n/tt-cyrl.json
languages/i18n/udm.json
languages/i18n/uk.json
languages/i18n/wuu.json
languages/i18n/yi.json
languages/i18n/zh-hans.json
languages/i18n/zh-hant.json
languages/messages/MessagesBn.php
languages/messages/MessagesKu_latn.php
languages/messages/MessagesWuu.php
maintenance/archives/patch-externallinks-el_index_60.sql [new file with mode: 0644]
maintenance/backup.inc
maintenance/importImages.inc [deleted file]
maintenance/importImages.php
maintenance/mssql/tables.sql
maintenance/oracle/archives/patch-externallinks-el_index_60.sql [new file with mode: 0644]
maintenance/oracle/tables.sql
maintenance/orphans.php
maintenance/postgres/tables.sql
maintenance/tables.sql
maintenance/view.php [new file with mode: 0644]
package.json
resources/Resources.php
resources/src/jquery.tipsy/jquery.tipsy.js
resources/src/mediawiki.language/languages/he.js [deleted file]
resources/src/mediawiki.language/languages/ru.js [deleted file]
resources/src/mediawiki.language/languages/uk.js [deleted file]
resources/src/mediawiki.language/mediawiki.language.js
resources/src/mediawiki.legacy/shared.css
resources/src/mediawiki.skinning/elements.css
resources/src/mediawiki.special/mediawiki.special.apisandbox.js
resources/src/mediawiki.special/mediawiki.special.changeslist.css
resources/src/mediawiki.special/mediawiki.special.watchlist.js
resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less
resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less
resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js
resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
resources/src/mediawiki/api.js
resources/src/mediawiki/api/watch.js
resources/src/mediawiki/htmlform/hide-if.js
resources/src/mediawiki/htmlform/styles.css
resources/src/mediawiki/mediawiki.searchSuggest.js
resources/src/mediawiki/page/watch.js
resources/src/startup.js
tests/parser/parserTests.txt
tests/phan/bin/phan
tests/phan/bin/postprocess-phan.php [new file with mode: 0644]
tests/phan/config.php
tests/phpunit/MediaWikiTestCase.php
tests/phpunit/ResourceLoaderTestCase.php
tests/phpunit/includes/BlockTest.php
tests/phpunit/includes/MessageTest.php
tests/phpunit/includes/TestLogger.php
tests/phpunit/includes/TitlePermissionTest.php
tests/phpunit/includes/WatchedItemStoreUnitTest.php
tests/phpunit/includes/api/ApiBaseTest.php
tests/phpunit/includes/api/ApiErrorFormatterTest.php
tests/phpunit/includes/api/ApiRevisionDeleteTest.php
tests/phpunit/includes/filerepo/StoreBatchTest.php
tests/phpunit/includes/media/MediaWikiMediaTestCase.php
tests/phpunit/includes/registration/CoreVersionCheckerTest.php [deleted file]
tests/phpunit/includes/registration/ExtensionProcessorTest.php
tests/phpunit/includes/registration/VersionCheckerTest.php [new file with mode: 0644]
tests/phpunit/includes/resourceloader/ResourceLoaderContextTest.php
tests/phpunit/includes/resourceloader/ResourceLoaderTest.php
tests/phpunit/includes/specials/SpecialEditWatchlistTest.php
tests/phpunit/includes/specials/SpecialRecentchangesTest.php
tests/phpunit/includes/user/UserTest.php
tests/phpunit/languages/classes/LanguageHeTest.php
tests/qunit/suites/resources/mediawiki.api/mediawiki.api.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js
tests/qunit/suites/resources/startup.test.js

index 5ff4ca9..43f21ef 100644 (file)
@@ -22,11 +22,19 @@ production.
   code for ApiBase::parseMsg() will no longer work.
 * ApiBase::$messageMap is no longer public. Code attempting to access it will
   result in a PHP fatal error.
-* $wgUserEmailUseReplyTo is now false by default to work around restrictive DMARC policies.
+* $wgUserEmailUseReplyTo is now true by default to work around restrictive DMARC policies.
+* Subpages are now enabled by default in the Template namespace. Set
+  $wgNamespacesWithSubpages[NS_TEMPLATE] to false to keep the old behavior.
+* $wgRunJobsAsync is now false by default (T142751). This change only affects
+  wikis with $wgJobRunRate > 0.
 
 === New features in 1.29 ===
 * (T5233) A cookie can now be set when a user is autoblocked, to track that user if
   they move to a new IP address. This is disabled by default.
+* Added ILocalizedException interface to standardize the use of localized
+  exceptions, largely so the API can handle them more sensibly.
+* Blocks created automatically by MediaWiki, such as for configured proxies or
+  dnsbls, are now indicated as such and use a new i18n message when displayed.
 
 === External library changes in 1.29 ===
 
@@ -38,6 +46,8 @@ production.
 ==== Removed and replaced external libraries ====
 
 === Bug fixes in 1.29 ===
+* (T62604) Core parser functions returning a number now format the number according
+  to the page content language, not wiki content language.
 
 === Action API changes in 1.29 ===
 * Submitting sensitive authentication request parameters to action=clientlogin,
@@ -50,6 +60,8 @@ production.
   using the new 'errorformat', 'errorlang', and 'errorsuselocal' parameters.
 * API error codes may have changed. Most notably, errors from modules using
   parameter prefixes (e.g. all query submodules) will no longer be prefixed.
+* ApiPageSet-using modules will report the 'invalidreason' using the specified
+  'errorformat'.
 * action=emailuser may return a "Warnings" status, and now returns 'warnings' and
   'errors' subelements (as applicable) instead of 'message'.
 * action=imagerotate returns an 'errors' subelement rather than 'errormessage'.
@@ -65,6 +77,8 @@ production.
   'stasherrors' rather than a 'stashfailed' text string.
 * action=watch reports 'errors' and 'warnings' instead of a single 'error', and
   no longer returns a 'message' on success.
+* Added action=validatepassword to validate passwords for the account creation
+  and password change forms.
 
 === Action API internal changes in 1.29 ===
 * New methods were added to ApiBase to handle errors and warnings using i18n
@@ -119,6 +133,10 @@ changes to languages because of Phabricator reports.
 * WikiPage::prepareTextForEdit() (deprecated in 1.21) was removed.
 * WikiPage::getText() (deprecated in 1.21) was removed.
 * Article::fetchContent() (deprecated in 1.21) was removed.
+* User::getPassword() (deprecated in 1.27) was removed.
+* User::getTemporaryPassword() (deprecated in 1.27) was removed.
+* User::isPasswordReminderThrottled() (deprecated in 1.27) was removed.
+* FSRepo (deprecated in 1.19) was removed.
 
 == Compatibility ==
 
index e079686..38bf7cd 100644 (file)
@@ -147,6 +147,7 @@ $wgAutoloadLocalClasses = [
        'ApiUpload' => __DIR__ . '/includes/api/ApiUpload.php',
        'ApiUsageException' => __DIR__ . '/includes/api/ApiUsageException.php',
        'ApiUserrights' => __DIR__ . '/includes/api/ApiUserrights.php',
+       'ApiValidatePassword' => __DIR__ . '/includes/api/ApiValidatePassword.php',
        'ApiWatch' => __DIR__ . '/includes/api/ApiWatch.php',
        'ArchivedFile' => __DIR__ . '/includes/filerepo/file/ArchivedFile.php',
        'ArrayDiffFormatter' => __DIR__ . '/includes/diff/ArrayDiffFormatter.php',
@@ -260,6 +261,7 @@ $wgAutoloadLocalClasses = [
        'Collation' => __DIR__ . '/includes/collation/Collation.php',
        'CollationCkb' => __DIR__ . '/includes/collation/CollationCkb.php',
        'CollationEt' => __DIR__ . '/includes/collation/CollationEt.php',
+       'CollationFa' => __DIR__ . '/includes/collation/CollationFa.php',
        'CommandLineInc' => __DIR__ . '/maintenance/commandLine.inc',
        'CommandLineInstaller' => __DIR__ . '/maintenance/install.php',
        'CompareParserCache' => __DIR__ . '/maintenance/compareParserCache.php',
@@ -293,7 +295,6 @@ $wgAutoloadLocalClasses = [
        'CopyJobQueue' => __DIR__ . '/maintenance/copyJobQueue.php',
        'CoreParserFunctions' => __DIR__ . '/includes/parser/CoreParserFunctions.php',
        'CoreTagHooks' => __DIR__ . '/includes/parser/CoreTagHooks.php',
-       'CoreVersionChecker' => __DIR__ . '/includes/registration/CoreVersionChecker.php',
        'CreateAndPromote' => __DIR__ . '/maintenance/createAndPromote.php',
        'CreateFileOp' => __DIR__ . '/includes/libs/filebackend/fileop/CreateFileOp.php',
        'CreditsAction' => __DIR__ . '/includes/actions/CreditsAction.php',
@@ -446,7 +447,6 @@ $wgAutoloadLocalClasses = [
        'FSFileBackendList' => __DIR__ . '/includes/libs/filebackend/FSFileBackend.php',
        'FSFileOpHandle' => __DIR__ . '/includes/libs/filebackend/FSFileBackend.php',
        'FSLockManager' => __DIR__ . '/includes/libs/lockmanager/FSLockManager.php',
-       'FSRepo' => __DIR__ . '/includes/filerepo/FSRepo.php',
        'FakeAuthTemplate' => __DIR__ . '/includes/specialpage/LoginSignupSpecialPage.php',
        'FakeConverter' => __DIR__ . '/languages/FakeConverter.php',
        'FakeMaintenance' => __DIR__ . '/maintenance/Maintenance.php',
@@ -598,6 +598,7 @@ $wgAutoloadLocalClasses = [
        'ILBFactory' => __DIR__ . '/includes/libs/rdbms/lbfactory/ILBFactory.php',
        'ILoadBalancer' => __DIR__ . '/includes/libs/rdbms/loadbalancer/ILoadBalancer.php',
        'ILoadMonitor' => __DIR__ . '/includes/libs/rdbms/loadmonitor/ILoadMonitor.php',
+       'ILocalizedException' => __DIR__ . '/includes/exception/LocalizedException.php',
        'IMaintainableDatabase' => __DIR__ . '/includes/libs/rdbms/database/IMaintainableDatabase.php',
        'IP' => __DIR__ . '/includes/libs/IP.php',
        'IPSet' => __DIR__ . '/includes/compat/IPSetCompat.php',
@@ -615,6 +616,7 @@ $wgAutoloadLocalClasses = [
        'ImageListPager' => __DIR__ . '/includes/specials/pagers/ImageListPager.php',
        'ImagePage' => __DIR__ . '/includes/page/ImagePage.php',
        'ImageQueryPage' => __DIR__ . '/includes/specialpage/ImageQueryPage.php',
+       'ImportImages' => __DIR__ . '/maintenance/importImages.php',
        'ImportLogFormatter' => __DIR__ . '/includes/logging/ImportLogFormatter.php',
        'ImportReporter' => __DIR__ . '/includes/specials/SpecialImport.php',
        'ImportSiteScripts' => __DIR__ . '/maintenance/importSiteScripts.php',
@@ -694,7 +696,6 @@ $wgAutoloadLocalClasses = [
        'LanguageFi' => __DIR__ . '/languages/classes/LanguageFi.php',
        'LanguageGa' => __DIR__ . '/languages/classes/LanguageGa.php',
        'LanguageGan' => __DIR__ . '/languages/classes/LanguageGan.php',
-       'LanguageHe' => __DIR__ . '/languages/classes/LanguageHe.php',
        'LanguageHsb' => __DIR__ . '/languages/classes/LanguageHsb.php',
        'LanguageHu' => __DIR__ . '/languages/classes/LanguageHu.php',
        'LanguageHy' => __DIR__ . '/languages/classes/LanguageHy.php',
@@ -759,6 +760,7 @@ $wgAutoloadLocalClasses = [
        'LocalSettingsGenerator' => __DIR__ . '/includes/installer/LocalSettingsGenerator.php',
        'LocalisationCache' => __DIR__ . '/includes/cache/localisation/LocalisationCache.php',
        'LocalisationCacheBulkLoad' => __DIR__ . '/includes/cache/localisation/LocalisationCacheBulkLoad.php',
+       'LocalizedException' => __DIR__ . '/includes/exception/LocalizedException.php',
        'LockManager' => __DIR__ . '/includes/libs/lockmanager/LockManager.php',
        'LockManagerGroup' => __DIR__ . '/includes/filebackend/lockmanager/LockManagerGroup.php',
        'LogEntry' => __DIR__ . '/includes/logging/LogEntry.php',
@@ -803,6 +805,7 @@ $wgAutoloadLocalClasses = [
        'MagicWordArray' => __DIR__ . '/includes/MagicWordArray.php',
        'MailAddress' => __DIR__ . '/includes/mail/MailAddress.php',
        'MainConfigDependency' => __DIR__ . '/includes/cache/CacheDependency.php',
+       'MaintainableDBConnRef' => __DIR__ . '/includes/libs/rdbms/database/MaintainableDBConnRef.php',
        'Maintenance' => __DIR__ . '/maintenance/Maintenance.php',
        'MaintenanceFormatInstallDoc' => __DIR__ . '/maintenance/formatInstallDoc.php',
        'MakeTestEdits' => __DIR__ . '/maintenance/makeTestEdits.php',
@@ -1422,7 +1425,7 @@ $wgAutoloadLocalClasses = [
        'TablePager' => __DIR__ . '/includes/pager/TablePager.php',
        'TagLogFormatter' => __DIR__ . '/includes/logging/TagLogFormatter.php',
        'TempFSFile' => __DIR__ . '/includes/libs/filebackend/fsfile/TempFSFile.php',
-       'TempFileRepo' => __DIR__ . '/includes/filerepo/FileRepo.php',
+       'TempFileRepo' => __DIR__ . '/includes/filerepo/TempFileRepo.php',
        'TemplateParser' => __DIR__ . '/includes/TemplateParser.php',
        'TemplatesOnThisPageFormatter' => __DIR__ . '/includes/TemplatesOnThisPageFormatter.php',
        'TestFileOpPerformance' => __DIR__ . '/maintenance/fileOpPerfTest.php',
@@ -1523,7 +1526,9 @@ $wgAutoloadLocalClasses = [
        'UzConverter' => __DIR__ . '/languages/classes/LanguageUz.php',
        'VFormHTMLForm' => __DIR__ . '/includes/htmlform/VFormHTMLForm.php',
        'ValidateRegistrationFile' => __DIR__ . '/maintenance/validateRegistrationFile.php',
+       'VersionChecker' => __DIR__ . '/includes/registration/VersionChecker.php',
        'ViewAction' => __DIR__ . '/includes/actions/ViewAction.php',
+       'ViewCLI' => __DIR__ . '/maintenance/view.php',
        'VirtualRESTService' => __DIR__ . '/includes/libs/virtualrest/VirtualRESTService.php',
        'VirtualRESTServiceClient' => __DIR__ . '/includes/libs/virtualrest/VirtualRESTServiceClient.php',
        'WANObjectCache' => __DIR__ . '/includes/libs/objectcache/WANObjectCache.php',
index f57b9ce..8e98710 100644 (file)
@@ -53,7 +53,7 @@
                "monolog/monolog": "~1.18.2",
                "nikic/php-parser": "2.1.0",
                "nmred/kafka-php": "0.1.5",
-               "phpunit/phpunit": "4.8.24",
+               "phpunit/phpunit": "4.8.31",
                "wikimedia/avro": "1.7.7"
        },
        "suggest": {
diff --git a/docs/extension.schema.json b/docs/extension.schema.json
deleted file mode 100644 (file)
index 30feaef..0000000
+++ /dev/null
@@ -1,719 +0,0 @@
-{
-       "$schema": "http://json-schema.org/schema#",
-       "description": "MediaWiki extension.json schema",
-       "type": "object",
-       "properties": {
-               "manifest_version": {
-                       "type": "integer",
-                       "description": "Version of the extension.json schema the extension.json file is in.",
-                       "required": true
-               },
-               "name": {
-                       "type": "string",
-                       "description": "The extension's canonical name.",
-                       "required": true
-               },
-               "namemsg": {
-                       "type": "string",
-                       "description": "i18n message key of the extension's name."
-               },
-               "type": {
-                       "type": "string",
-                       "description": "The extension's type, as an index to $wgExtensionCredits.",
-                       "default": "other"
-               },
-               "author": {
-                       "type": [
-                               "string",
-                               "array"
-                       ],
-                       "description": "Extension's authors.",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "version": {
-                       "type": "string",
-                       "description": "The version of this release of the extension."
-               },
-               "url": {
-                       "type": "string",
-                       "description": "URL to the homepage for the extension.",
-                       "format": "uri"
-               },
-               "description": {
-                       "type": "string",
-                       "description": "Raw description of the extension."
-               },
-               "descriptionmsg": {
-                       "type": "string",
-                       "description": "Message key for a i18n message describing the extension."
-               },
-               "license-name": {
-                       "type": "string",
-                       "description": "SPDX identifier for the license under which the extension is released."
-               },
-               "requires": {
-                       "type": "object",
-                       "description": "Indicates what versions of MediaWiki core are required. This syntax may be extended in the future, for example to check dependencies between other extensions.",
-                       "properties": {
-                               "MediaWiki": {
-                                       "type": "string",
-                                       "description": "Version constraint string against MediaWiki core."
-                               }
-                       }
-               },
-               "ResourceFileModulePaths": {
-                       "type": "object",
-                       "description": "Default paths to use for all ResourceLoader file modules",
-                       "additionalProperties": false,
-                       "properties": {
-                               "localBasePath": {
-                                       "type": "string",
-                                       "description": "Base path to prepend to all local paths, relative to current directory"
-                               },
-                               "remoteExtPath": {
-                                       "type": "string",
-                                       "description": "Base path to prepend to all remote paths, relative to $wgExtensionAssetsPath"
-                               },
-                               "remoteSkinPath": {
-                                       "type": "string",
-                                       "description": "Base path to prepend to all remote paths, relative to $wgStylePath"
-                               }
-                       }
-               },
-               "ResourceModules": {
-                       "type": "object",
-                       "description": "ResourceLoader modules to register",
-                       "patternProperties": {
-                               "^[a-zA-Z0-9-\\.]+$": {
-                                       "type": "object",
-                                       "anyOf": [
-                                               {
-                                                       "description": "A ResourceLoaderFileModule definition",
-                                                       "additionalProperties": false,
-                                                       "properties": {
-                                                               "localBasePath": {
-                                                                       "type": "string",
-                                                                       "description": "Base path to prepend to all local paths in $options. Defaults to $IP"
-                                                               },
-                                                               "remoteBasePath": {
-                                                                       "type": "string",
-                                                                       "description": "Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath"
-                                                               },
-                                                               "remoteExtPath": {
-                                                                       "type": "string",
-                                                                       "description": "Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath"
-                                                               },
-                                                               "skipFunction": {
-                                                                       "type": "string",
-                                                                       "description": "Path to a file containing a JavaScript \"skip function\", if desired."
-                                                               },
-                                                               "scripts": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Scripts to always include (array of file paths)",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "languageScripts": {
-                                                                       "type": "object",
-                                                                       "description": "Scripts to include in specific language contexts (mapping of language code to file path(s))",
-                                                                       "patternProperties": {
-                                                                               "^[a-zA-Z0-9-]{2,}$": {
-                                                                                       "type": [
-                                                                                               "string",
-                                                                                               "array"
-                                                                                       ],
-                                                                                       "items": {
-                                                                                               "type": "string"
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               },
-                                                               "skinScripts": {
-                                                                       "type": "object",
-                                                                       "description": "Scripts to include in specific skin contexts (mapping of skin name to script(s)",
-                                                                       "patternProperties": {
-                                                                               ".+": {
-                                                                                       "type": [
-                                                                                               "string",
-                                                                                               "array"
-                                                                                       ],
-                                                                                       "items": {
-                                                                                               "type": "string"
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               },
-                                                               "debugScripts": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Scripts to include in debug contexts",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "loaderScripts": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Scripts to include in the startup module",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "dependencies": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Modules which must be loaded before this module",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "styles": {
-                                                                       "type": ["string", "array", "object"],
-                                                                       "description": "Styles to always load",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "skinStyles": {
-                                                                       "type": "object",
-                                                                       "description": "Styles to include in specific skin contexts (mapping of skin name to style(s))",
-                                                                       "patternProperties": {
-                                                                               ".+": {
-                                                                                       "type": [
-                                                                                               "string",
-                                                                                               "array"
-                                                                                       ],
-                                                                                       "items": {
-                                                                                               "type": "string"
-                                                                                       }
-                                                                               }
-                                                                       }
-                                                               },
-                                                               "messages": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "Messages to always load",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "group": {
-                                                                       "type": "string",
-                                                                       "description": "Group with which this module should be loaded"
-                                                               },
-                                                               "deprecated": {
-                                                                       "type": ["object", "boolean"],
-                                                                       "description": "Whether the module is deprecated and usage is discouraged. Either a boolean or an object with key message can be used to customise deprecation message."
-                                                               },
-                                                               "position": {
-                                                                       "type": "string",
-                                                                       "description": "Position on the page to load this module at",
-                                                                       "enum": [
-                                                                               "bottom",
-                                                                               "top"
-                                                                       ]
-                                                               },
-                                                               "templates": {
-                                                                       "type": ["object", "array"],
-                                                                       "description": "Templates to be loaded for client-side usage"
-                                                               },
-                                                               "targets": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "ResourceLoader target the module can run on",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "noflip": {
-                                                                       "type": "boolean",
-                                                                       "description": "Whether to skip CSSJanus LTR-to-RTL flipping for this module. Recommended for styles imported from libraries that already properly handle their RTL styles. Default is false, meaning CSSJanus will be applied on RTL-mode output."
-                                                               }
-                                                       }
-                                               },
-                                               {
-                                                       "description": "A ResourceLoaderWikiModule definition",
-                                                       "additionalProperties": false,
-                                                       "properties": {
-                                                               "class": {
-                                                                       "enum": ["ResourceLoaderWikiModule"]
-                                                               },
-                                                               "group": {
-                                                                       "type": "string",
-                                                                       "description": "Group with which this module should be loaded"
-                                                               },
-                                                               "position": {
-                                                                       "type": "string",
-                                                                       "description": "Position on the page to load this module at",
-                                                                       "enum": [
-                                                                               "bottom",
-                                                                               "top"
-                                                                       ]
-                                                               },
-                                                               "targets": {
-                                                                       "type": ["string", "array"],
-                                                                       "description": "ResourceLoader target the module can run on",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "scripts": {
-                                                                       "type": "array",
-                                                                       "description": "A list of on-wiki pages containing JavaScript that should be loaded",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               },
-                                                               "styles": {
-                                                                       "type": "array",
-                                                                       "description": "A list of on-wiki pages containing CSS that should be loaded",
-                                                                       "items": {
-                                                                               "type": "string"
-                                                                       }
-                                                               }
-                                                       }
-                                               },
-                                               {
-                                                       "description": "A ResourceLoaderImageModule definition",
-                                                       "additionalProperties": false,
-                                                       "properties": {
-                                                               "class": {
-                                                                       "enum": ["ResourceLoaderImageModule"]
-                                                               },
-                                                               "data": {
-                                                                       "type": "string"
-                                                               },
-                                                               "prefix": {
-                                                                       "type": "string"
-                                                               },
-                                                               "selector": {
-                                                                       "type": "string"
-                                                               },
-                                                               "selectorWithoutVariant": {
-                                                                       "type": "string"
-                                                               },
-                                                               "selectorWithVariant": {
-                                                                       "type": "string"
-                                                               },
-                                                               "variants": {
-                                                                       "type": "object"
-                                                               },
-                                                               "images": {
-                                                                       "type": "object"
-                                                               },
-                                                               "position": {
-                                                                       "enum": [
-                                                                               "top",
-                                                                               "bottom"
-                                                                       ]
-                                                               }
-                                                       }
-                                               },
-                                               {
-                                                       "description": "An arbitrary ResourceLoaderModule definition",
-                                                       "properties": {
-                                                               "class": {
-                                                                       "type": "string",
-                                                                       "pattern": "^((?!ResourceLoader(File|Image)Module).)*$"
-                                                               }
-                                                       },
-                                                       "required": ["class"]
-                                               }
-                                       ]
-                               }
-                       }
-               },
-               "ResourceModuleSkinStyles": {
-                       "type": "object",
-                       "description": "ResourceLoader modules for custom skin styles"
-               },
-               "ResourceLoaderSources": {
-                       "type": "object",
-                       "description": "ResourceLoader sources to register"
-               },
-               "ResourceLoaderLESSVars": {
-                       "type": "object",
-                       "description": "ResourceLoader LESS variables"
-               },
-               "ConfigRegistry": {
-                       "type": "object",
-                       "description": "Registry of factory functions to create Config objects"
-               },
-               "SessionProviders": {
-                       "type": "object",
-                       "description": "Session providers"
-               },
-               "AuthManagerAutoConfig": {
-                       "type": "object",
-                       "description": "AuthManager auto-configuration",
-                       "additionalProperties": false,
-                       "properties": {
-                               "preauth": {
-                                       "type": "object",
-                                       "description": "Pre-authentication providers"
-                               },
-                               "primaryauth": {
-                                       "type": "object",
-                                       "description": "Primary authentication providers"
-                               },
-                               "secondaryauth": {
-                                       "type": "object",
-                                       "description": "Secondary authentication providers"
-                               }
-                       }
-               },
-               "CentralIdLookupProviders": {
-                       "type": "object",
-                       "description": "Central ID lookup providers"
-               },
-               "ChangeCredentialsBlacklist": {
-                       "type": "object",
-                       "description": "AuthenticationRequest classes which can only be used internally for credentials change"
-               },
-               "RemoveCredentialsBlacklist": {
-                       "type": "object",
-                       "description": "AuthenticationRequest classes which can only be used internally for credentials removal"
-               },
-               "namespaces": {
-                       "type": "array",
-                       "description": "Method to add extra namespaces",
-                       "items": {
-                               "type": "object",
-                               "properties": {
-                                       "id": {
-                                               "type": "integer"
-                                       },
-                                       "constant": {
-                                               "type": "string"
-                                       },
-                                       "name": {
-                                               "type": "string"
-                                       },
-                                       "gender": {
-                                               "type": "object",
-                                               "properties": {
-                                                       "male": {
-                                                               "type": "string"
-                                                       },
-                                                       "female": {
-                                                               "type": "string"
-                                                       }
-                                               }
-                                       },
-                                       "subpages": {
-                                               "type": "boolean",
-                                               "default": false
-                                       },
-                                       "content": {
-                                               "type": "boolean",
-                                               "default": false
-                                       },
-                                       "defaultcontentmodel": {
-                                               "type": "string"
-                                       },
-                                       "protection": {
-                                               "type": ["string", "array"],
-                                               "description": "Userright(s) required to edit in this namespace"
-                                       },
-                                       "capitallinkoverride": {
-                                               "type": "boolean",
-                                               "description": "Set $wgCapitalLinks on a per-namespace basis"
-                                       },
-                                       "conditional": {
-                                               "type": "boolean",
-                                               "description": "Whether the namespace is conditional upon configuration and should not be registered (requires separate registration via a hook)",
-                                               "default": false
-                                       }
-                               },
-                               "required": ["id", "constant", "name"]
-                       }
-               },
-               "TrackingCategories": {
-                       "type": "array",
-                       "description": "Tracking category message keys",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "DefaultUserOptions": {
-                       "type": "object",
-                       "description": "Default values of user options"
-               },
-               "HiddenPrefs": {
-                       "type": "array",
-                       "description": "Preferences users cannot set",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "GroupPermissions": {
-                       "type": "object",
-                       "description": "Default permissions to give to user groups",
-                       "patternProperties": {
-                               "^[a-z]+$": {
-                                       "type": "object",
-                                       "patternProperties": {
-                                               "^[a-z]+$": {
-                                                       "type": "boolean"
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "RevokePermissions": {
-                       "type": "object",
-                       "description": "Default permissions to revoke from user groups",
-                       "patternProperties": {
-                               "^[a-z]+$": {
-                                       "type": "object",
-                                       "patternProperties": {
-                                               "^[a-z]+$": {
-                                                       "type": "boolean"
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "GrantPermissions": {
-                       "type": "object",
-                       "description": "Map of permissions granted to authorized consumers to their bundles, called 'grants'",
-                       "patternProperties": {
-                               "^[a-z]+$": {
-                                       "type": "object",
-                                       "patternProperties": {
-                                               "^[a-z]+$": {
-                                                       "type": "boolean"
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "GrantPermissionGroups": {
-                       "type": "object",
-                       "description": "Map of grants to their UI grouping",
-                       "patternProperties": {
-                               "^[a-z]+$": {
-                                       "type": "string"
-                               }
-                       }
-               },
-               "ImplicitGroups": {
-                       "type": "array",
-                       "description": "Implicit groups"
-               },
-               "GroupsAddToSelf": {
-                       "type": "object",
-                       "description": "Groups a user can add to themselves"
-               },
-               "GroupsRemoveFromSelf": {
-                       "type": "object",
-                       "description": "Groups a user can remove from themselves"
-               },
-               "AddGroups": {
-                       "type": "object",
-                       "description": "Groups a user can add to users"
-               },
-               "RemoveGroups": {
-                       "type": "object",
-                       "description": "Groups a user can remove from users"
-               },
-               "AvailableRights": {
-                       "type": "array",
-                       "description": "User rights added by the extension",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "ContentHandlers": {
-                       "type": "object",
-                       "description": "Mapping of model ID to class name",
-                       "patternProperties": {
-                               "^[A-Za-z]+$": {
-                                       "type": "string"
-                               }
-                       }
-               },
-               "RateLimits": {
-                       "type": "object",
-                       "description": "Rate limits"
-               },
-               "RecentChangesFlags": {
-                       "type": "object",
-                       "description": "Flags (letter symbols) shown on RecentChanges pages"
-               },
-               "MediaHandlers": {
-                       "type": "object",
-                       "description": "Plugins for media file type handling. Each entry in the array maps a MIME type to a PHP class name."
-               },
-               "ExtensionFunctions": {
-                       "type": [
-                               "array",
-                               "string"
-                       ],
-                       "description": "Function to call after setup has finished",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "ExtensionMessagesFiles": {
-                       "type": "object",
-                       "description": "File paths containing PHP internationalization data"
-               },
-               "MessagesDirs": {
-                       "type": "object",
-                       "description": "Directory paths containing JSON internationalization data"
-               },
-               "ExtensionEntryPointListFiles": {
-                       "type": "object"
-               },
-               "SpecialPages": {
-                       "type": "object",
-                       "description": "SpecialPages implemented in this extension (mapping of page name to class name)"
-               },
-               "AutoloadClasses": {
-                       "type": "object"
-               },
-               "Hooks": {
-                       "type": [ "string", "object" ],
-                       "description": "Hooks this extension uses (mapping of hook name to callback)"
-               },
-               "JobClasses": {
-                       "type": "object",
-                       "description": "Job types this extension implements (mapping of job type to class name)"
-               },
-               "LogTypes": {
-                       "type": "array",
-                       "description": "List of new log types this extension uses"
-               },
-               "LogRestrictions": {
-                       "type": "object"
-               },
-               "FilterLogTypes": {
-                       "type": "object"
-               },
-               "ActionFilteredLogs": {
-                       "type": "object",
-                       "description": "List of log types which can be filtered by log actions",
-                       "patternProperties": {
-                               "^[a-z-]+$": {
-                                       "type": "object",
-                                       "patternProperties": {
-                                               "^[a-z-]+$": {
-                                                       "type": "array",
-                                                       "items": {
-                                                               "type": "string"
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "LogNames": {
-                       "type": "object"
-               },
-               "LogHeaders": {
-                       "type": "object"
-               },
-               "LogActions": {
-                       "type": "object"
-               },
-               "LogActionsHandlers": {
-                       "type": "object"
-               },
-               "Actions": {
-                       "type": "object"
-               },
-               "APIModules": {
-                       "type": "object"
-               },
-               "APIFormatModules": {
-                       "type": "object"
-               },
-               "APIMetaModules": {
-                       "type": "object"
-               },
-               "APIPropModules": {
-                       "type": "object"
-               },
-               "APIListModules": {
-                       "type": "object"
-               },
-               "ValidSkinNames": {
-                       "type": "object"
-               },
-               "FeedClasses": {
-                       "type": "object",
-                       "description": "Available feeds objects"
-               },
-               "SkinOOUIThemes": {
-                       "type": "object"
-               },
-               "PasswordPolicy": {
-                       "type": "object",
-                       "description": "Password policies"
-               },
-               "FileExtensions": {
-                       "type": "array",
-                       "description": "Preferred file extensions for uploading",
-                       "items": {
-                               "type": "string"
-                       }
-               },
-               "callback": {
-                       "type": [
-                               "array",
-                               "string"
-                       ],
-                       "description": "A function to be called right after MediaWiki processes this file"
-               },
-               "config_prefix": {
-                       "type": "string",
-                       "default": "wg",
-                       "description": "Prefix to put in front of configuration settings when exporting them to $GLOBALS"
-               },
-               "config": {
-                       "type": "object",
-                       "description": "Configuration options for this extension",
-                       "patternProperties": {
-                               "^[a-zA-Z_\u007f-\u00ff][a-zA-Z0-9_\u007f-\u00ff]*$": {
-                                       "type": "object",
-                                       "properties": {
-                                               "value": {
-                                                       "required": true
-                                               },
-                                               "merge_strategy": {
-                                                       "type": "string",
-                                                       "enum": [
-                                                               "array_merge_recursive",
-                                                               "array_replace_recursive",
-                                                               "array_plus_2d",
-                                                               "array_plus",
-                                                               "array_merge"
-                                                       ],
-                                                       "default": "array_merge"
-                                               },
-                                               "path": {
-                                                       "description": "Whether this should be interpreted as a filesystem path, relative to extension directory root",
-                                                       "type": "boolean",
-                                                       "default": false
-                                               },
-                                               "description": {
-                                                       "type": ["string", "array"],
-                                                       "description": "A description of the config setting, mostly for documentation/developers"
-                                               }
-                                       }
-                               }
-                       }
-               },
-               "ParserTestFiles": {
-                       "type": "array",
-                       "description": "Parser test suite files to be run by parserTests.php when no specific filename is passed to it"
-               },
-               "ServiceWiringFiles": {
-                       "type": "array",
-                       "description": "List of service wiring files to be loaded by the default instance of MediaWikiServices"
-               },
-               "load_composer_autoloader": {
-                       "type": "boolean",
-                       "description": "Load the composer autoloader for this extension, if one is present"
-               }
-       }
-}
diff --git a/docs/extension.schema.v2.json b/docs/extension.schema.v2.json
new file mode 100644 (file)
index 0000000..a5543d1
--- /dev/null
@@ -0,0 +1,727 @@
+{
+       "$schema": "http://json-schema.org/schema#",
+       "description": "MediaWiki extension.json schema",
+       "type": "object",
+       "properties": {
+               "manifest_version": {
+                       "type": "integer",
+                       "description": "Version of the extension.json schema the extension.json file is in.",
+                       "required": true
+               },
+               "name": {
+                       "type": "string",
+                       "description": "The extension's canonical name.",
+                       "required": true
+               },
+               "namemsg": {
+                       "type": "string",
+                       "description": "i18n message key of the extension's name."
+               },
+               "type": {
+                       "type": "string",
+                       "description": "The extension's type, as an index to $wgExtensionCredits.",
+                       "default": "other"
+               },
+               "author": {
+                       "type": [
+                               "string",
+                               "array"
+                       ],
+                       "description": "Extension's authors.",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "version": {
+                       "type": "string",
+                       "description": "The version of this release of the extension."
+               },
+               "url": {
+                       "type": "string",
+                       "description": "URL to the homepage for the extension.",
+                       "format": "uri"
+               },
+               "description": {
+                       "type": "string",
+                       "description": "Raw description of the extension."
+               },
+               "descriptionmsg": {
+                       "type": "string",
+                       "description": "Message key for a i18n message describing the extension."
+               },
+               "license-name": {
+                       "type": "string",
+                       "description": "SPDX identifier for the license under which the extension is released."
+               },
+               "requires": {
+                       "type": "object",
+                       "description": "Indicates what versions of MediaWiki core or extensions are required. This syntax may be extended in the future, for example to check dependencies between other services.",
+                       "properties": {
+                               "MediaWiki": {
+                                       "type": "string",
+                                       "description": "Version constraint string against MediaWiki core."
+                               },
+                               "extensions": {
+                                       "type": "object",
+                                       "description": "Set of version constraint strings against specific extensions."
+                               },
+                               "skins": {
+                                       "type": "object",
+                                       "description": "Set of version constraint strings against specific skins."
+                               }
+                       }
+               },
+               "ResourceFileModulePaths": {
+                       "type": "object",
+                       "description": "Default paths to use for all ResourceLoader file modules",
+                       "additionalProperties": false,
+                       "properties": {
+                               "localBasePath": {
+                                       "type": "string",
+                                       "description": "Base path to prepend to all local paths, relative to current directory"
+                               },
+                               "remoteExtPath": {
+                                       "type": "string",
+                                       "description": "Base path to prepend to all remote paths, relative to $wgExtensionAssetsPath"
+                               },
+                               "remoteSkinPath": {
+                                       "type": "string",
+                                       "description": "Base path to prepend to all remote paths, relative to $wgStylePath"
+                               }
+                       }
+               },
+               "ResourceModules": {
+                       "type": "object",
+                       "description": "ResourceLoader modules to register",
+                       "patternProperties": {
+                               "^[a-zA-Z0-9-\\.]+$": {
+                                       "type": "object",
+                                       "anyOf": [
+                                               {
+                                                       "description": "A ResourceLoaderFileModule definition",
+                                                       "additionalProperties": false,
+                                                       "properties": {
+                                                               "localBasePath": {
+                                                                       "type": "string",
+                                                                       "description": "Base path to prepend to all local paths in $options. Defaults to $IP"
+                                                               },
+                                                               "remoteBasePath": {
+                                                                       "type": "string",
+                                                                       "description": "Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath"
+                                                               },
+                                                               "remoteExtPath": {
+                                                                       "type": "string",
+                                                                       "description": "Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath"
+                                                               },
+                                                               "skipFunction": {
+                                                                       "type": "string",
+                                                                       "description": "Path to a file containing a JavaScript \"skip function\", if desired."
+                                                               },
+                                                               "scripts": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Scripts to always include (array of file paths)",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "languageScripts": {
+                                                                       "type": "object",
+                                                                       "description": "Scripts to include in specific language contexts (mapping of language code to file path(s))",
+                                                                       "patternProperties": {
+                                                                               "^[a-zA-Z0-9-]{2,}$": {
+                                                                                       "type": [
+                                                                                               "string",
+                                                                                               "array"
+                                                                                       ],
+                                                                                       "items": {
+                                                                                               "type": "string"
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "skinScripts": {
+                                                                       "type": "object",
+                                                                       "description": "Scripts to include in specific skin contexts (mapping of skin name to script(s)",
+                                                                       "patternProperties": {
+                                                                               ".+": {
+                                                                                       "type": [
+                                                                                               "string",
+                                                                                               "array"
+                                                                                       ],
+                                                                                       "items": {
+                                                                                               "type": "string"
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "debugScripts": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Scripts to include in debug contexts",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "loaderScripts": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Scripts to include in the startup module",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "dependencies": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Modules which must be loaded before this module",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "styles": {
+                                                                       "type": ["string", "array", "object"],
+                                                                       "description": "Styles to always load",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "skinStyles": {
+                                                                       "type": "object",
+                                                                       "description": "Styles to include in specific skin contexts (mapping of skin name to style(s))",
+                                                                       "patternProperties": {
+                                                                               ".+": {
+                                                                                       "type": [
+                                                                                               "string",
+                                                                                               "array"
+                                                                                       ],
+                                                                                       "items": {
+                                                                                               "type": "string"
+                                                                                       }
+                                                                               }
+                                                                       }
+                                                               },
+                                                               "messages": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "Messages to always load",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "group": {
+                                                                       "type": "string",
+                                                                       "description": "Group with which this module should be loaded"
+                                                               },
+                                                               "deprecated": {
+                                                                       "type": ["object", "boolean"],
+                                                                       "description": "Whether the module is deprecated and usage is discouraged. Either a boolean or an object with key message can be used to customise deprecation message."
+                                                               },
+                                                               "position": {
+                                                                       "type": "string",
+                                                                       "description": "Position on the page to load this module at",
+                                                                       "enum": [
+                                                                               "bottom",
+                                                                               "top"
+                                                                       ]
+                                                               },
+                                                               "templates": {
+                                                                       "type": ["object", "array"],
+                                                                       "description": "Templates to be loaded for client-side usage"
+                                                               },
+                                                               "targets": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "ResourceLoader target the module can run on",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "noflip": {
+                                                                       "type": "boolean",
+                                                                       "description": "Whether to skip CSSJanus LTR-to-RTL flipping for this module. Recommended for styles imported from libraries that already properly handle their RTL styles. Default is false, meaning CSSJanus will be applied on RTL-mode output."
+                                                               }
+                                                       }
+                                               },
+                                               {
+                                                       "description": "A ResourceLoaderWikiModule definition",
+                                                       "additionalProperties": false,
+                                                       "properties": {
+                                                               "class": {
+                                                                       "enum": ["ResourceLoaderWikiModule"]
+                                                               },
+                                                               "group": {
+                                                                       "type": "string",
+                                                                       "description": "Group with which this module should be loaded"
+                                                               },
+                                                               "position": {
+                                                                       "type": "string",
+                                                                       "description": "Position on the page to load this module at",
+                                                                       "enum": [
+                                                                               "bottom",
+                                                                               "top"
+                                                                       ]
+                                                               },
+                                                               "targets": {
+                                                                       "type": ["string", "array"],
+                                                                       "description": "ResourceLoader target the module can run on",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "scripts": {
+                                                                       "type": "array",
+                                                                       "description": "A list of on-wiki pages containing JavaScript that should be loaded",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               },
+                                                               "styles": {
+                                                                       "type": "array",
+                                                                       "description": "A list of on-wiki pages containing CSS that should be loaded",
+                                                                       "items": {
+                                                                               "type": "string"
+                                                                       }
+                                                               }
+                                                       }
+                                               },
+                                               {
+                                                       "description": "A ResourceLoaderImageModule definition",
+                                                       "additionalProperties": false,
+                                                       "properties": {
+                                                               "class": {
+                                                                       "enum": ["ResourceLoaderImageModule"]
+                                                               },
+                                                               "data": {
+                                                                       "type": "string"
+                                                               },
+                                                               "prefix": {
+                                                                       "type": "string"
+                                                               },
+                                                               "selector": {
+                                                                       "type": "string"
+                                                               },
+                                                               "selectorWithoutVariant": {
+                                                                       "type": "string"
+                                                               },
+                                                               "selectorWithVariant": {
+                                                                       "type": "string"
+                                                               },
+                                                               "variants": {
+                                                                       "type": "object"
+                                                               },
+                                                               "images": {
+                                                                       "type": "object"
+                                                               },
+                                                               "position": {
+                                                                       "enum": [
+                                                                               "top",
+                                                                               "bottom"
+                                                                       ]
+                                                               }
+                                                       }
+                                               },
+                                               {
+                                                       "description": "An arbitrary ResourceLoaderModule definition",
+                                                       "properties": {
+                                                               "class": {
+                                                                       "type": "string",
+                                                                       "pattern": "^((?!ResourceLoader(File|Image)Module).)*$"
+                                                               }
+                                                       },
+                                                       "required": ["class"]
+                                               }
+                                       ]
+                               }
+                       }
+               },
+               "ResourceModuleSkinStyles": {
+                       "type": "object",
+                       "description": "ResourceLoader modules for custom skin styles"
+               },
+               "ResourceLoaderSources": {
+                       "type": "object",
+                       "description": "ResourceLoader sources to register"
+               },
+               "ResourceLoaderLESSVars": {
+                       "type": "object",
+                       "description": "ResourceLoader LESS variables"
+               },
+               "ConfigRegistry": {
+                       "type": "object",
+                       "description": "Registry of factory functions to create Config objects"
+               },
+               "SessionProviders": {
+                       "type": "object",
+                       "description": "Session providers"
+               },
+               "AuthManagerAutoConfig": {
+                       "type": "object",
+                       "description": "AuthManager auto-configuration",
+                       "additionalProperties": false,
+                       "properties": {
+                               "preauth": {
+                                       "type": "object",
+                                       "description": "Pre-authentication providers"
+                               },
+                               "primaryauth": {
+                                       "type": "object",
+                                       "description": "Primary authentication providers"
+                               },
+                               "secondaryauth": {
+                                       "type": "object",
+                                       "description": "Secondary authentication providers"
+                               }
+                       }
+               },
+               "CentralIdLookupProviders": {
+                       "type": "object",
+                       "description": "Central ID lookup providers"
+               },
+               "ChangeCredentialsBlacklist": {
+                       "type": "object",
+                       "description": "AuthenticationRequest classes which can only be used internally for credentials change"
+               },
+               "RemoveCredentialsBlacklist": {
+                       "type": "object",
+                       "description": "AuthenticationRequest classes which can only be used internally for credentials removal"
+               },
+               "namespaces": {
+                       "type": "array",
+                       "description": "Method to add extra namespaces",
+                       "items": {
+                               "type": "object",
+                               "properties": {
+                                       "id": {
+                                               "type": "integer"
+                                       },
+                                       "constant": {
+                                               "type": "string"
+                                       },
+                                       "name": {
+                                               "type": "string"
+                                       },
+                                       "gender": {
+                                               "type": "object",
+                                               "properties": {
+                                                       "male": {
+                                                               "type": "string"
+                                                       },
+                                                       "female": {
+                                                               "type": "string"
+                                                       }
+                                               }
+                                       },
+                                       "subpages": {
+                                               "type": "boolean",
+                                               "default": false
+                                       },
+                                       "content": {
+                                               "type": "boolean",
+                                               "default": false
+                                       },
+                                       "defaultcontentmodel": {
+                                               "type": "string"
+                                       },
+                                       "protection": {
+                                               "type": ["string", "array"],
+                                               "description": "Userright(s) required to edit in this namespace"
+                                       },
+                                       "capitallinkoverride": {
+                                               "type": "boolean",
+                                               "description": "Set $wgCapitalLinks on a per-namespace basis"
+                                       },
+                                       "conditional": {
+                                               "type": "boolean",
+                                               "description": "Whether the namespace is conditional upon configuration and should not be registered (requires separate registration via a hook)",
+                                               "default": false
+                                       }
+                               },
+                               "required": ["id", "constant", "name"]
+                       }
+               },
+               "TrackingCategories": {
+                       "type": "array",
+                       "description": "Tracking category message keys",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "DefaultUserOptions": {
+                       "type": "object",
+                       "description": "Default values of user options"
+               },
+               "HiddenPrefs": {
+                       "type": "array",
+                       "description": "Preferences users cannot set",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "GroupPermissions": {
+                       "type": "object",
+                       "description": "Default permissions to give to user groups",
+                       "patternProperties": {
+                               "^[a-z]+$": {
+                                       "type": "object",
+                                       "patternProperties": {
+                                               "^[a-z]+$": {
+                                                       "type": "boolean"
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "RevokePermissions": {
+                       "type": "object",
+                       "description": "Default permissions to revoke from user groups",
+                       "patternProperties": {
+                               "^[a-z]+$": {
+                                       "type": "object",
+                                       "patternProperties": {
+                                               "^[a-z]+$": {
+                                                       "type": "boolean"
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "GrantPermissions": {
+                       "type": "object",
+                       "description": "Map of permissions granted to authorized consumers to their bundles, called 'grants'",
+                       "patternProperties": {
+                               "^[a-z]+$": {
+                                       "type": "object",
+                                       "patternProperties": {
+                                               "^[a-z]+$": {
+                                                       "type": "boolean"
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "GrantPermissionGroups": {
+                       "type": "object",
+                       "description": "Map of grants to their UI grouping",
+                       "patternProperties": {
+                               "^[a-z]+$": {
+                                       "type": "string"
+                               }
+                       }
+               },
+               "ImplicitGroups": {
+                       "type": "array",
+                       "description": "Implicit groups"
+               },
+               "GroupsAddToSelf": {
+                       "type": "object",
+                       "description": "Groups a user can add to themselves"
+               },
+               "GroupsRemoveFromSelf": {
+                       "type": "object",
+                       "description": "Groups a user can remove from themselves"
+               },
+               "AddGroups": {
+                       "type": "object",
+                       "description": "Groups a user can add to users"
+               },
+               "RemoveGroups": {
+                       "type": "object",
+                       "description": "Groups a user can remove from users"
+               },
+               "AvailableRights": {
+                       "type": "array",
+                       "description": "User rights added by the extension",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "ContentHandlers": {
+                       "type": "object",
+                       "description": "Mapping of model ID to class name",
+                       "patternProperties": {
+                               "^[A-Za-z]+$": {
+                                       "type": "string"
+                               }
+                       }
+               },
+               "RateLimits": {
+                       "type": "object",
+                       "description": "Rate limits"
+               },
+               "RecentChangesFlags": {
+                       "type": "object",
+                       "description": "Flags (letter symbols) shown on RecentChanges pages"
+               },
+               "MediaHandlers": {
+                       "type": "object",
+                       "description": "Plugins for media file type handling. Each entry in the array maps a MIME type to a PHP class name."
+               },
+               "ExtensionFunctions": {
+                       "type": [
+                               "array",
+                               "string"
+                       ],
+                       "description": "Function to call after setup has finished",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "ExtensionMessagesFiles": {
+                       "type": "object",
+                       "description": "File paths containing PHP internationalization data"
+               },
+               "MessagesDirs": {
+                       "type": "object",
+                       "description": "Directory paths containing JSON internationalization data"
+               },
+               "ExtensionEntryPointListFiles": {
+                       "type": "object"
+               },
+               "SpecialPages": {
+                       "type": "object",
+                       "description": "SpecialPages implemented in this extension (mapping of page name to class name)"
+               },
+               "AutoloadClasses": {
+                       "type": "object"
+               },
+               "Hooks": {
+                       "type": [ "string", "object" ],
+                       "description": "Hooks this extension uses (mapping of hook name to callback)"
+               },
+               "JobClasses": {
+                       "type": "object",
+                       "description": "Job types this extension implements (mapping of job type to class name)"
+               },
+               "LogTypes": {
+                       "type": "array",
+                       "description": "List of new log types this extension uses"
+               },
+               "LogRestrictions": {
+                       "type": "object"
+               },
+               "FilterLogTypes": {
+                       "type": "object"
+               },
+               "ActionFilteredLogs": {
+                       "type": "object",
+                       "description": "List of log types which can be filtered by log actions",
+                       "patternProperties": {
+                               "^[a-z-]+$": {
+                                       "type": "object",
+                                       "patternProperties": {
+                                               "^[a-z-]+$": {
+                                                       "type": "array",
+                                                       "items": {
+                                                               "type": "string"
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "LogNames": {
+                       "type": "object"
+               },
+               "LogHeaders": {
+                       "type": "object"
+               },
+               "LogActions": {
+                       "type": "object"
+               },
+               "LogActionsHandlers": {
+                       "type": "object"
+               },
+               "Actions": {
+                       "type": "object"
+               },
+               "APIModules": {
+                       "type": "object"
+               },
+               "APIFormatModules": {
+                       "type": "object"
+               },
+               "APIMetaModules": {
+                       "type": "object"
+               },
+               "APIPropModules": {
+                       "type": "object"
+               },
+               "APIListModules": {
+                       "type": "object"
+               },
+               "ValidSkinNames": {
+                       "type": "object"
+               },
+               "FeedClasses": {
+                       "type": "object",
+                       "description": "Available feeds objects"
+               },
+               "SkinOOUIThemes": {
+                       "type": "object"
+               },
+               "PasswordPolicy": {
+                       "type": "object",
+                       "description": "Password policies"
+               },
+               "FileExtensions": {
+                       "type": "array",
+                       "description": "Preferred file extensions for uploading",
+                       "items": {
+                               "type": "string"
+                       }
+               },
+               "callback": {
+                       "type": [
+                               "array",
+                               "string"
+                       ],
+                       "description": "A function to be called right after MediaWiki processes this file"
+               },
+               "config_prefix": {
+                       "type": "string",
+                       "default": "wg",
+                       "description": "Prefix to put in front of configuration settings when exporting them to $GLOBALS"
+               },
+               "config": {
+                       "type": "object",
+                       "description": "Configuration options for this extension",
+                       "patternProperties": {
+                               "^[a-zA-Z_\u007f-\u00ff][a-zA-Z0-9_\u007f-\u00ff]*$": {
+                                       "type": "object",
+                                       "properties": {
+                                               "value": {
+                                                       "required": true
+                                               },
+                                               "merge_strategy": {
+                                                       "type": "string",
+                                                       "enum": [
+                                                               "array_merge_recursive",
+                                                               "array_replace_recursive",
+                                                               "array_plus_2d",
+                                                               "array_plus",
+                                                               "array_merge"
+                                                       ],
+                                                       "default": "array_merge"
+                                               },
+                                               "path": {
+                                                       "description": "Whether this should be interpreted as a filesystem path, relative to extension directory root",
+                                                       "type": "boolean",
+                                                       "default": false
+                                               },
+                                               "description": {
+                                                       "type": ["string", "array"],
+                                                       "description": "A description of the config setting, mostly for documentation/developers"
+                                               }
+                                       }
+                               }
+                       }
+               },
+               "ParserTestFiles": {
+                       "type": "array",
+                       "description": "Parser test suite files to be run by parserTests.php when no specific filename is passed to it"
+               },
+               "ServiceWiringFiles": {
+                       "type": "array",
+                       "description": "List of service wiring files to be loaded by the default instance of MediaWikiServices"
+               },
+               "load_composer_autoloader": {
+                       "type": "boolean",
+                       "description": "Load the composer autoloader for this extension, if one is present"
+               }
+       }
+}
index 7efd5d2..b165285 100644 (file)
@@ -592,6 +592,10 @@ Use this hook to extend action=tokens with new token types.
 &$tokenTypes: supported token types in format 'type' => callback function
   used to retrieve this type of tokens.
 
+'ApiValidatePassword': Called from ApiValidatePassword.
+$module: ApiValidatePassword instance.
+&$r: Result array.
+
 'Article::MissingArticleConditions': Before fetching deletion & move log entries
 to display a message of a non-existing page being deleted/moved, give extensions
 a chance to hide their (unrelated) log entries.
@@ -759,6 +763,7 @@ $flags: Flags passed to WikiPage::doEditContent()
 $revision: New Revision of the article
 $status: Status object about to be returned by doEditContent()
 $baseRevId: the rev ID (or false) this edit was based on
+$undidRevId: the rev ID (or 0) this edit undid
 
 'ArticleUndelete': When one or more revisions of an article are restored.
 &$title: Title corresponding to the article restored
@@ -1190,6 +1195,18 @@ $page: SpecialPage object for DeletedContributions
 $row: the DB row for this line
 &$classes: the classes to add to the surrounding <li>
 
+'DifferenceEngineAfterLoadNewText': called in DifferenceEngine::loadNewText()
+after the new revision's content has been loaded into the class member variable
+$differenceEngine->mNewContent but before returning true from this function.
+$differenceEngine: DifferenceEngine object
+
+'DifferenceEngineLoadTextAfterNewContentIsLoaded': called in
+DifferenceEngine::loadText() after the new revision's content has been loaded
+into the class member variable $differenceEngine->mNewContent but before
+checking if the variable's value is null.
+This hook can be used to inject content into said class member variable.
+$differenceEngine: DifferenceEngine object
+
 'DifferenceEngineMarkPatrolledLink': Allows extensions to change the "mark as patrolled" link
 which is shown both on the diff header as well as on the bottom of a page, usually
 wrapped in a span element which has class="patrollink".
@@ -1268,6 +1285,12 @@ $differenceEngine: DifferenceEngine object
 object into the diff view
 $out: OutputPage object
 
+'DifferenceEngineShowDiffPageMaybeShowMissingRevision': called in
+DifferenceEngine::showDiffPage() when revision data cannot be loaded.
+Return false in order to prevent displaying the missing revision message
+(i.e. to prevent DifferenceEngine::showMissingRevision() from being called).
+$differenceEngine: DifferenceEngine object
+
 'DiffRevisionTools': Override or extend the revision tools available from the
 diff view, i.e. undo, etc.
 $newRev: Revision object of the "new" revision
@@ -2367,6 +2390,7 @@ $revision: New Revision of the article (can be null for edits that change
   nothing)
 $status: Status object about to be returned by doEditContent()
 $baseRevId: the rev ID (or false) this edit was based on
+$undidRevId: the rev ID (or 0) this edit undid
 
 'PageHistoryBeforeList': When a history page list is about to be constructed.
 &$article: the article that the history is loading for
index 8663d03..20cb614 100644 (file)
@@ -74,6 +74,9 @@ class Block {
        /** @var bool */
        protected $isAutoblocking;
 
+       /** @var string|null */
+       protected $systemBlockType;
+
        # TYPE constants
        const TYPE_USER = 1;
        const TYPE_IP = 2;
@@ -99,6 +102,10 @@ class Block {
         *     blockEmail bool      Disallow sending emails
         *     allowUsertalk bool   Allow the target to edit its own talk page
         *     byText string        Username of the blocker (for foreign users)
+        *     systemBlock string   Indicate that this block is automatically
+        *                          created by MediaWiki rather than being stored
+        *                          in the database. Value is a string to return
+        *                          from self::getSystemBlockType().
         *
         * @since 1.26 accepts $options array instead of individual parameters; order
         * of parameters above reflects the original order
@@ -119,6 +126,7 @@ class Block {
                        'blockEmail'      => false,
                        'allowUsertalk'   => false,
                        'byText'          => '',
+                       'systemBlock'     => null,
                ];
 
                if ( func_num_args() > 1 || !is_array( $options ) ) {
@@ -162,6 +170,7 @@ class Block {
                $this->prevents( 'createaccount', (bool)$options['createAccount'] );
 
                $this->mFromMaster = false;
+               $this->systemBlockType = $options['systemBlock'];
        }
 
        /**
@@ -461,6 +470,11 @@ class Block {
         */
        public function insert( $dbw = null ) {
                global $wgBlockDisablesLogin;
+
+               if ( $this->getSystemBlockType() !== null ) {
+                       throw new MWException( 'Cannot insert a system block into the database' );
+               }
+
                wfDebug( "Block::insert; timestamp {$this->mTimestamp}\n" );
 
                if ( $dbw === null ) {
@@ -741,6 +755,11 @@ class Block {
                        return false;
                }
 
+               # Don't autoblock for system blocks
+               if ( $this->getSystemBlockType() !== null ) {
+                       throw new MWException( 'Cannot autoblock from a system block' );
+               }
+
                # Check for presence on the autoblock whitelist.
                if ( self::isWhitelistedFromAutoblocks( $autoblockIP ) ) {
                        return false;
@@ -934,6 +953,14 @@ class Block {
                return $this->mId;
        }
 
+       /**
+        * Get the system block type, if any
+        * @return string|null
+        */
+       public function getSystemBlockType() {
+               return $this->systemBlockType;
+       }
+
        /**
         * Get/set a flag determining whether the master is used for reads
         *
@@ -1419,8 +1446,7 @@ class Block {
 
        /**
         * Set the 'BlockID' cookie to this block's ID and expiry time. The cookie's expiry will be
-        * the same as the block's, unless it's greater than $wgCookieExpiration in which case
-        * $wgCookieExpiration will be used instead (defaults to 30 days).
+        * the same as the block's, to a maximum of 24 hours.
         *
         * An empty value can also be set, in order to retain the cookie but remove the block ID
         * (e.g. as used in User::getBlockedStatus).
@@ -1430,18 +1456,18 @@ class Block {
         */
        public function setCookie( WebResponse $response, $setEmpty = false ) {
                // Calculate the default expiry time.
-               $config = RequestContext::getMain()->getConfig();
-               $defaultExpiry = wfTimestamp() + $config->get( 'CookieExpiration' );
+               $maxExpiryTime = wfTimestamp( TS_MW, wfTimestamp() + ( 24 * 60 * 60 ) );
 
                // Use the Block's expiry time only if it's less than the default.
-               $expiry = wfTimestamp( TS_UNIX, $this->getExpiry() );
-               if ( $expiry > $defaultExpiry ) {
-                       // The *default* default expiry is 30 days.
-                       $expiry = $defaultExpiry;
+               $expiryTime = $this->getExpiry();
+               if ( $expiryTime === 'infinity' || $expiryTime > $maxExpiryTime ) {
+                       $expiryTime = $maxExpiryTime;
                }
 
+               // Set the cookie. Reformat the MediaWiki datetime as a Unix timestamp for the cookie.
                $cookieValue = $setEmpty ? '' : $this->getId();
-               $response->setCookie( 'BlockID', $cookieValue, $expiry );
+               $expiryValue = DateTime::createFromFormat( "YmdHis", $expiryTime );
+               $response->setCookie( 'BlockID', $cookieValue, $expiryValue->format( "U" ) );
        }
 
        /**
@@ -1469,14 +1495,18 @@ class Block {
                 * This could be a username, an IP range, or a single IP. */
                $intended = $this->getTarget();
 
+               $systemBlockType = $this->getSystemBlockType();
+
                $lang = $context->getLanguage();
                return [
-                       $this->mAuto ? 'autoblockedtext' : 'blockedtext',
+                       $systemBlockType !== null
+                               ? 'systemblockedtext'
+                               : ( $this->mAuto ? 'autoblockedtext' : 'blockedtext' ),
                        $link,
                        $reason,
                        $context->getRequest()->getIP(),
                        $this->getByName(),
-                       $this->getId(),
+                       $systemBlockType !== null ? $systemBlockType : $this->getId(),
                        $lang->formatExpiry( $this->mExpiry ),
                        (string)$intended,
                        $lang->userTimeAndDate( $this->mTimestamp, $context->getUser() ),
index 1ebd605..d558dbc 100644 (file)
@@ -168,7 +168,7 @@ class Category {
         * @param Title $title Optional title object for the category represented by
         *   the given row. May be provided if it is already known, to avoid having
         *   to re-create a title object later.
-        * @return Category
+        * @return Category|false
         */
        public static function newFromRow( $row, $title = null ) {
                $cat = new self();
index e908a16..3274480 100644 (file)
@@ -4016,6 +4016,7 @@ $wgNamespacesWithSubpages = [
        NS_FILE_TALK => true,
        NS_MEDIAWIKI => true,
        NS_MEDIAWIKI_TALK => true,
+       NS_TEMPLATE => true,
        NS_TEMPLATE_TALK => true,
        NS_HELP => true,
        NS_HELP_TALK => true,
@@ -8104,10 +8105,7 @@ $wgJobRunRate = 1;
  *
  * @since 1.23
  */
-$wgRunJobsAsync = (
-       !function_exists( 'register_postsend_function' ) &&
-       !function_exists( 'fastcgi_finish_request' )
-);
+$wgRunJobsAsync = false;
 
 /**
  * Number of rows to update per job
@@ -8462,6 +8460,23 @@ $wgCSPFalsePositiveUrls = [
        'https://d5p.de17a.com' => true,
 ];
 
+/**
+ * The following variables define 3 user experience levels:
+ *
+ *  - newcomer: has not yet reached the 'learner' level
+ *
+ *  - learner: has at least $wgLearnerEdits and has been
+ *             a member for $wgLearnerMemberSince days
+ *             but has not yet reached the 'experienced' level.
+ *
+ *  - experienced: has at least $wgExperiencedUserEdits edits and
+ *                 has been a member for $wgExperiencedUserMemberSince days.
+ */
+$wgLearnerEdits = 10;
+$wgLearnerMemberSince = 4; # days
+$wgExperiencedUserEdits = 500;
+$wgExperiencedUserMemberSince = 30; # days
+
 /**
  * For really cool vim folding this needs to be at the end:
  * vim: foldmarker=@{,@} foldmethod=marker
index f37ce34..1f871e1 100644 (file)
@@ -295,7 +295,7 @@ class EditPage {
        /** @var bool Has a summary been preset using GET parameter &summary= ? */
        public $hasPresetSummary = false;
 
-       /** @var bool */
+       /** @var Revision|bool */
        public $mBaseRevision = false;
 
        /** @var bool */
@@ -661,7 +661,11 @@ class EditPage {
                $remove = [];
                foreach ( $permErrors as $error ) {
                        if ( ( $this->preview || $this->diff )
-                               && ( $error[0] == 'blockedtext' || $error[0] == 'autoblockedtext' )
+                               && (
+                                       $error[0] == 'blockedtext' ||
+                                       $error[0] == 'autoblockedtext' ||
+                                       $error[0] == 'systemblockedtext'
+                               )
                        ) {
                                $remove[] = $error;
                        }
@@ -2142,7 +2146,8 @@ class EditPage {
                        false,
                        $wgUser,
                        $content->getDefaultFormat(),
-                       $this->changeTags
+                       $this->changeTags,
+                       $this->undidRev
                );
 
                if ( !$doEditStatus->isOK() ) {
index de7e8c2..4351acc 100644 (file)
@@ -46,7 +46,7 @@ class GitInfo {
        protected $cache = [];
 
        /**
-        * Map of repo URLs to viewer URLs. Access via static method getViewers().
+        * @var array|false Map of repo URLs to viewer URLs. Access via static method getViewers().
         */
        private static $viewers = false;
 
index b3ccc56..6549fdd 100644 (file)
@@ -545,7 +545,7 @@ function wfAppendQuery( $url, $query ) {
  * @param string $url Either fully-qualified or a local path + query
  * @param string $defaultProto One of the PROTO_* constants. Determines the
  *    protocol to use if $url or $wgServer is protocol-relative
- * @return string Fully-qualified URL, current-path-relative URL or false if
+ * @return string|false Fully-qualified URL, current-path-relative URL or false if
  *    no valid URL can be constructed
  */
 function wfExpandUrl( $url, $defaultProto = PROTO_CURRENT ) {
@@ -1385,12 +1385,16 @@ function wfGetLangObj( $langcode = false ) {
  * @see Message::__construct
  */
 function wfMessage( $key /*...*/ ) {
+       $message = new Message( $key );
+
+       // We call Message::params() to reduce code duplication
        $params = func_get_args();
        array_shift( $params );
-       if ( isset( $params[0] ) && is_array( $params[0] ) ) {
-               $params = $params[0];
+       if ( $params ) {
+               call_user_func_array( [ $message, 'params' ], $params );
        }
-       return new Message( $key, $params );
+
+       return $message;
 }
 
 /**
@@ -3518,7 +3522,7 @@ function wfIsBadImage( $name, $contextTitle = false, $blacklist = null ) {
        # Run the extension hook
        $bad = false;
        if ( !Hooks::run( 'BadImage', [ $name, &$bad ] ) ) {
-               return $bad;
+               return (bool)$bad;
        }
 
        $cache = ObjectCache::getLocalServerInstance( 'hash' );
index b17a2f5..3d86201 100644 (file)
@@ -239,7 +239,7 @@ class HistoryBlobStub {
        }
 
        /**
-        * @return string
+        * @return string|false
         */
        function getText() {
                if ( isset( self::$blobCache[$this->mOldId] ) ) {
index 7e5cc7d..fd67613 100644 (file)
@@ -488,18 +488,32 @@ class Message implements MessageSpecifier, Serializable {
         *
         * @since 1.17
         *
-        * @param mixed ... Parameters as strings, or a single argument that is
-        * an array of strings.
+        * @param mixed ... Parameters as strings or arrays from
+        *  Message::numParam() and the like, or a single array of parameters.
         *
         * @return Message $this
         */
        public function params( /*...*/ ) {
                $args = func_get_args();
-               if ( isset( $args[0] ) && is_array( $args[0] ) ) {
-                       $args = $args[0];
+
+               // If $args has only one entry and it's an array, then it's either a
+               // non-varargs call or it happens to be a call with just a single
+               // "special" parameter. Since the "special" parameters don't have any
+               // numeric keys, we'll test that to differentiate the cases.
+               if ( count( $args ) === 1 && isset( $args[0] ) && is_array( $args[0] ) ) {
+                       if ( $args[0] === [] ) {
+                               $args = [];
+                       } else {
+                               foreach ( $args[0] as $key => $value ) {
+                                       if ( is_int( $key ) ) {
+                                               $args = $args[0];
+                                               break;
+                                       }
+                               }
+                       }
                }
-               $args_values = array_values( $args );
-               $this->parameters = array_merge( $this->parameters, $args_values );
+
+               $this->parameters = array_merge( $this->parameters, array_values( $args ) );
                return $this;
        }
 
@@ -1040,9 +1054,9 @@ class Message implements MessageSpecifier, Serializable {
        /**
         * @since 1.22
         *
-        * @param number $period
+        * @param int $period
         *
-        * @return number[] Array with a single "period" key.
+        * @return int[] Array with a single "period" key.
         */
        public static function timeperiodParam( $period ) {
                return [ 'period' => $period ];
@@ -1291,8 +1305,9 @@ class Message implements MessageSpecifier, Serializable {
         */
        protected function formatListParam( array $params, $listType, $format ) {
                if ( !isset( self::$listTypeMap[$listType] ) ) {
-                       $warning = 'Invalid list type for message "' . $this->getKey() . '": ' .
-                               htmlspecialchars( serialize( $param ) );
+                       $warning = 'Invalid list type for message "' . $this->getKey() . '": '
+                               . htmlspecialchars( $listType )
+                               . ' (params are ' . htmlspecialchars( serialize( $params ) ) . ')';
                        trigger_error( $warning, E_USER_WARNING );
                        $e = new Exception;
                        wfDebugLog( 'Bug58676', $warning . "\n" . $e->getTraceAsString() );
index bae871e..9bae882 100644 (file)
@@ -2176,7 +2176,7 @@ class OutputPage extends ContextSource {
         * if there isn't one. This is used by Skin to determine whether to enable
         * JavaScript frame-breaking, for clients that don't support X-Frame-Options.
         *
-        * @return string
+        * @return string|false
         */
        public function getFrameOptions() {
                $config = $this->getConfig();
@@ -2303,7 +2303,7 @@ class OutputPage extends ContextSource {
                                $response->header( "Content-Type: text/html; charset=utf-8" );
                                if ( $config->get( 'DebugRedirects' ) ) {
                                        $url = htmlspecialchars( $redirect );
-                                       print "<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
+                                       print "<!DOCTYPE html>\n<html>\n<head>\n<title>Redirect</title>\n</head>\n<body>\n";
                                        print "<p>Location: <a href=\"$url\">$url</a></p>\n";
                                        print "</body>\n</html>\n";
                                } else {
index 049b32f..cc6fc4a 100644 (file)
@@ -364,7 +364,7 @@ class PathRouterPatternReplacer {
         * difference between a $1 that was not replaced and a $1 that was part of
         * the content a $1 was replaced with.
         * @param string $value
-        * @return string
+        * @return string|false
         */
        public function replace( $value ) {
                $this->error = false;
index d40e0c1..cf8e7b8 100644 (file)
@@ -1218,7 +1218,8 @@ class Preferences {
                $pixels = $context->msg( 'unit-pixel' )->text();
 
                foreach ( $context->getConfig()->get( 'ImageLimits' ) as $index => $limits ) {
-                       $display = "{$limits[0]}×{$limits[1]}" . $pixels;
+                       // Note: A left-to-right marker (\u200e) is inserted, see T144386
+                       $display = "{$limits[0]}" . json_decode( '"\u200e"' ) . "×{$limits[1]}" . $pixels;
                        $ret[$display] = $index;
                }
 
index 04c17e4..48b1d72 100644 (file)
@@ -23,7 +23,7 @@
 /**
  * Handles searching prefixes of titles and finding any page
  * names that match. Used largely by the OpenSearch implementation.
- * @deprecated Since 1.27, Use SearchEngine::prefixSearchSubpages or SearchEngine::completionSearch
+ * @deprecated Since 1.27, Use SearchEngine::defaultPrefixSearch or SearchEngine::completionSearch
  *
  * @ingroup Search
  */
@@ -369,7 +369,7 @@ abstract class PrefixSearch {
 
 /**
  * Performs prefix search, returning Title objects
- * @deprecated Since 1.27, Use SearchEngine::prefixSearchSubpages or SearchEngine::completionSearch
+ * @deprecated Since 1.27, Use SearchEngine::defaultPrefixSearch or SearchEngine::completionSearch
  * @ingroup Search
  */
 class TitlePrefixSearch extends PrefixSearch {
index 451635e..454ffcc 100644 (file)
@@ -148,7 +148,7 @@ class ProtectionForm {
         *
         * @param string $action
         *
-        * @return string 14-char timestamp or "infinity", or false if the input was invalid
+        * @return string|false 14-char timestamp or "infinity", or false if the input was invalid
         */
        function getExpiry( $action ) {
                if ( $this->mExpirySelection[$action] == 'existing' ) {
index 81bba55..aea8488 100644 (file)
@@ -874,7 +874,7 @@ class Revision implements IDBAccessObject {
        /**
         * Fetch revision's user id without regard for the current user's permissions
         *
-        * @return string
+        * @return int
         * @deprecated since 1.25, use getUser( Revision::RAW )
         */
        public function getRawUser() {
@@ -1269,7 +1269,7 @@ class Revision implements IDBAccessObject {
         *   (same as the the wiki $row was loaded from) or false to indicate the local
         *   wiki (this is the default). Otherwise, it must be a symbolic wiki database
         *   identifier as understood by the LoadBalancer class.
-        * @return string Text the text requested or false on failure
+        * @return string|false Text the text requested or false on failure
         */
        public static function getRevisionText( $row, $prefix = 'old_', $wiki = false ) {
 
index 4fec472..ce82702 100644 (file)
@@ -71,8 +71,14 @@ return [
        },
 
        'SiteLookup' => function( MediaWikiServices $services ) {
-               // Use the default SiteStore as the SiteLookup implementation for now
-               return $services->getSiteStore();
+               $cacheFile = $services->getMainConfig()->get( 'SitesCacheFile' );
+
+               if ( $cacheFile !== false ) {
+                       return new FileBasedSiteLookup( $cacheFile );
+               } else {
+                       // Use the default SiteStore as the SiteLookup implementation for now
+                       return $services->getSiteStore();
+               }
        },
 
        'ConfigFactory' => function( MediaWikiServices $services ) {
index 885f926..8d9256b 100644 (file)
@@ -274,7 +274,7 @@ class SiteConfiguration {
         * @param string $from
         * @param string $to
         * @param string|array $in
-        * @return string
+        * @return string|array
         */
        function doReplace( $from, $to, $in ) {
                if ( is_string( $in ) ) {
index 3c51bae..c4584bd 100644 (file)
@@ -835,7 +835,7 @@ class Title implements LinkTarget {
        /**
         * Returns the DB name of the distant wiki which owns the object.
         *
-        * @return string The DB name
+        * @return string|false The DB name
         */
        public function getTransWikiID() {
                if ( !$this->isExternal() ) {
@@ -974,7 +974,7 @@ class Title implements LinkTarget {
        /**
         * Get the namespace text
         *
-        * @return string Namespace text
+        * @return string|false Namespace text
         */
        public function getNsText() {
                if ( $this->isExternal() ) {
@@ -1627,7 +1627,7 @@ class Title implements LinkTarget {
         *
         * @since 1.19 (r105919)
         * @param array|string $query
-        * @param bool $query2
+        * @param string|string[]|bool $query2
         * @return string
         */
        private static function fixUrlQueryArgs( $query, $query2 = false ) {
@@ -1663,8 +1663,8 @@ class Title implements LinkTarget {
         *
         * @see self::getLocalURL for the arguments.
         * @see wfExpandUrl
-        * @param array|string $query
-        * @param bool $query2
+        * @param string|string[] $query
+        * @param string|string[]|bool $query2
         * @param string $proto Protocol type to use in URL
         * @return string The URL
         */
@@ -1696,11 +1696,11 @@ class Title implements LinkTarget {
         *  valid to link, locally, to the current Title.
         * @see self::newFromText to produce a Title object.
         *
-        * @param string|array $query An optional query string,
+        * @param string|string[] $query An optional query string,
         *   not used for interwiki links. Can be specified as an associative array as well,
         *   e.g., array( 'action' => 'edit' ) (keys and values will be URL-escaped).
         *   Some query patterns will trigger various shorturl path replacements.
-        * @param array $query2 An optional secondary query array. This one MUST
+        * @param string|string[]|bool $query2 An optional secondary query array. This one MUST
         *   be an array. If a string is passed it will be interpreted as a deprecated
         *   variant argument and urlencoded into a variant= argument.
         *   This second query argument will be added to the $query
@@ -1795,7 +1795,7 @@ class Title implements LinkTarget {
         * The result obviously should not be URL-escaped, but does need to be
         * HTML-escaped if it's being output in HTML.
         *
-        * @param array $query
+        * @param string|string[] $query
         * @param bool $query2
         * @param string|int|bool $proto A PROTO_* constant on how the URL should be expanded,
         *                               or false (default) for no expansion
@@ -3703,23 +3703,28 @@ class Title implements LinkTarget {
         * @param bool $createRedirect Whether to create redirects from the old subpages to
         *     the new ones Ignored if the user doesn't have the 'suppressredirect' right
         * @return array Array with old page titles as keys, and strings (new page titles) or
-        *     arrays (errors) as values, or an error array with numeric indices if no pages
-        *     were moved
+        *     getUserPermissionsErrors()-like arrays (errors) as values, or a
+        *     getUserPermissionsErrors()-like error array with numeric indices if
+        *     no pages were moved
         */
        public function moveSubpages( $nt, $auth = true, $reason = '', $createRedirect = true ) {
                global $wgMaximumMovedPages;
                // Check permissions
                if ( !$this->userCan( 'move-subpages' ) ) {
-                       return [ 'cant-move-subpages' ];
+                       return [
+                               [ 'cant-move-subpages' ],
+                       ];
                }
                // Do the source and target namespaces support subpages?
                if ( !MWNamespace::hasSubpages( $this->getNamespace() ) ) {
-                       return [ 'namespace-nosubpages',
-                               MWNamespace::getCanonicalName( $this->getNamespace() ) ];
+                       return [
+                               [ 'namespace-nosubpages', MWNamespace::getCanonicalName( $this->getNamespace() ) ],
+                       ];
                }
                if ( !MWNamespace::hasSubpages( $nt->getNamespace() ) ) {
-                       return [ 'namespace-nosubpages',
-                               MWNamespace::getCanonicalName( $nt->getNamespace() ) ];
+                       return [
+                               [ 'namespace-nosubpages', MWNamespace::getCanonicalName( $nt->getNamespace() ) ],
+                       ];
                }
 
                $subpages = $this->getSubpages( $wgMaximumMovedPages + 1 );
@@ -3728,9 +3733,9 @@ class Title implements LinkTarget {
                foreach ( $subpages as $oldSubpage ) {
                        $count++;
                        if ( $count > $wgMaximumMovedPages ) {
-                               $retval[$oldSubpage->getPrefixedText()] =
-                                               [ 'movepage-max-pages',
-                                                       $wgMaximumMovedPages ];
+                               $retval[$oldSubpage->getPrefixedText()] = [
+                                       [ 'movepage-max-pages', $wgMaximumMovedPages ],
+                               ];
                                break;
                        }
 
@@ -4436,7 +4441,7 @@ class Title implements LinkTarget {
         * Get the last touched timestamp
         *
         * @param IDatabase $db Optional db
-        * @return string Last-touched timestamp
+        * @return string|false Last-touched timestamp
         */
        public function getTouched( $db = null ) {
                if ( $db === null ) {
index cc4779e..3cdc59c 100644 (file)
@@ -668,7 +668,7 @@ class WatchedItemStore implements StatsdAwareInterface {
 
        /**
         * @param User $user The user to set the timestamp for
-        * @param string $timestamp Set the update timestamp to this value
+        * @param string|null $timestamp Set the update timestamp to this value
         * @param LinkTarget[] $targets List of targets to update. Default to all targets
         *
         * @return bool success
@@ -687,9 +687,13 @@ class WatchedItemStore implements StatsdAwareInterface {
                        $conds[] = $batch->constructSet( 'wl', $dbw );
                }
 
+               if ( $timestamp !== null ) {
+                       $timestamp = $dbw->timestamp( $timestamp );
+               }
+
                $success = $dbw->update(
                        'watchlist',
-                       [ 'wl_notificationtimestamp' => $dbw->timestamp( $timestamp ) ],
+                       [ 'wl_notificationtimestamp' => $timestamp ],
                        $conds,
                        __METHOD__
                );
index 3ef3bc1..e7c9b83 100644 (file)
@@ -238,7 +238,7 @@ class WebRequest {
         * This is for use prior to Setup.php, when no WebRequest object is available.
         * At other times, use the non-static function getProtocol().
         *
-        * @return array
+        * @return string
         */
        public static function detectProtocol() {
                if ( ( !empty( $_SERVER['HTTPS'] ) && $_SERVER['HTTPS'] !== 'off' ) ||
@@ -1099,6 +1099,7 @@ class WebRequest {
                header( 'Content-Type: text/html' );
                $encUrl = htmlspecialchars( $url );
                echo <<<HTML
+<!DOCTYPE html>
 <html>
 <head>
 <title>Security redirect</title>
index 37f85ea..f7b8d2f 100644 (file)
@@ -141,7 +141,7 @@ class WikiMap {
         * @param string $wikiID Wiki'd id (generally database name)
         * @param string $page Page name (must be normalised before calling this function!)
         * @param string $text Link's text; optional, default to $page
-        * @return string HTML link or false if the wiki was not found
+        * @return string|false HTML link or false if the wiki was not found
         */
        public static function makeForeignLink( $wikiID, $page, $text = null ) {
                if ( !$text ) {
index 49b9ab7..5fb83b3 100644 (file)
@@ -261,28 +261,29 @@ class InfoAction extends FormlessAction {
                // Language in which the page content is (supposed to be) written
                $pageLang = $title->getPageLanguage()->getCode();
 
+               $pageLangHtml = $pageLang . ' - ' .
+                       Language::fetchLanguageName( $pageLang, $lang->getCode() );
+               // Link to Special:PageLanguage with pre-filled page title if user has permissions
                if ( $config->get( 'PageLanguageUseDB' )
-                       && $this->getTitle()->userCan( 'pagelang', $this->getUser() )
+                       && $title->userCan( 'pagelang', $user )
                ) {
-                       // Link to Special:PageLanguage with pre-filled page title if user has permissions
-                       $titleObj = SpecialPage::getTitleFor( 'PageLanguage', $title->getPrefixedText() );
-                       $langDisp = $linkRenderer->makeLink(
-                               $titleObj,
-                               $this->msg( 'pageinfo-language' )->text()
-                       );
-               } else {
-                       // Display just the message
-                       $langDisp = $this->msg( 'pageinfo-language' )->escaped();
+                       $pageLangHtml .= ' ' . $this->msg( 'parentheses' )->rawParams( $linkRenderer->makeLink(
+                               SpecialPage::getTitleValueFor( 'PageLanguage', $title->getPrefixedText() ),
+                               $this->msg( 'pageinfo-language-change' )->text()
+                       ) )->escaped();
                }
 
-               $pageInfo['header-basic'][] = [ $langDisp,
-                       Language::fetchLanguageName( $pageLang, $lang->getCode() )
-                       . ' ' . $this->msg( 'parentheses', $pageLang )->escaped() ];
+               $pageInfo['header-basic'][] = [
+                       $this->msg( 'pageinfo-language' )->escaped(),
+                       $pageLangHtml
+               ];
 
                // Content model of the page
                $modelHtml = htmlspecialchars( ContentHandler::getLocalizedName( $title->getContentModel() ) );
                // If the user can change it, add a link to Special:ChangeContentModel
-               if ( $title->quickUserCan( 'editcontentmodel' ) ) {
+               if ( $config->get( 'ContentHandlerUseDB' )
+                       && $title->userCan( 'editcontentmodel', $user )
+               ) {
                        $modelHtml .= ' ' . $this->msg( 'parentheses' )->rawParams( $linkRenderer->makeLink(
                                SpecialPage::getTitleValueFor( 'ChangeContentModel', $title->getPrefixedText() ),
                                $this->msg( 'pageinfo-content-model-change' )->text()
@@ -474,7 +475,7 @@ class InfoAction extends FormlessAction {
                        }
                        $expiry = $title->getRestrictionExpiry( $restrictionType );
                        $formattedexpiry = $this->msg( 'parentheses',
-                               $this->getLanguage()->formatExpiry( $expiry ) )->escaped();
+                               $lang->formatExpiry( $expiry ) )->escaped();
                        $message .= $this->msg( 'word-separator' )->escaped() . $formattedexpiry;
 
                        // Messages: restriction-edit, restriction-move, restriction-create,
index a40593f..c1ad947 100644 (file)
@@ -1627,6 +1627,12 @@ abstract class ApiBase extends ContextSource {
                                        'autoblocked',
                                        [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
                                ) );
+                       } elseif ( is_array( $error ) && $error[0] === 'systemblockedtext' && $user->getBlock() ) {
+                               $status->fatal( ApiMessage::create(
+                                       'apierror-systemblocked',
+                                       'blocked',
+                                       [ 'blockinfo' => ApiQueryUserInfo::getBlockInfo( $user->getBlock() ) ]
+                               ) );
                        } else {
                                call_user_func_array( [ $status, 'fatal' ], (array)$error );
                        }
@@ -1723,6 +1729,20 @@ abstract class ApiBase extends ContextSource {
                throw ApiUsageException::newWithMessage( $this, $msg, $code, $data, $httpCode );
        }
 
+       /**
+        * Abort execution with an error derived from an exception
+        *
+        * @since 1.29
+        * @param Exception|Throwable $exception See ApiErrorFormatter::getMessageFromException()
+        * @param array $options See ApiErrorFormatter::getMessageFromException()
+        * @throws ApiUsageException always
+        */
+       public function dieWithException( $exception, array $options = [] ) {
+               $this->dieWithError(
+                       $this->getErrorFormatter()->getMessageFromException( $exception, $options )
+               );
+       }
+
        /**
         * Adds a warning to the output, else dies
         *
@@ -2229,7 +2249,7 @@ abstract class ApiBase extends ContextSource {
         * "apihelp-{$this->getModulePath()}-description".
         *
         * @deprecated since 1.25
-        * @return Message|string|array
+        * @return Message|string|array|false
         */
        protected function getDescription() {
                return false;
@@ -2450,6 +2470,7 @@ abstract class ApiBase extends ContextSource {
                'confirmedittext' => 'confirmedittext',
                'blockedtext' => 'apierror-blocked',
                'autoblockedtext' => 'apierror-autoblocked',
+               'systemblockedtext' => 'apierror-systemblocked',
                'actionthrottledtext' => 'apierror-ratelimited',
                'alreadyrolled' => 'alreadyrolled',
                'cantrollback' => 'cantrollback',
index 6b56870..b45be31 100644 (file)
@@ -140,11 +140,9 @@ class ApiEditPage extends ApiBase {
                                        try {
                                                $content = ContentHandler::makeContent( $text, $this->getTitle() );
                                        } catch ( MWContentSerializationException $ex ) {
-                                               // @todo: Internationalize MWContentSerializationException
-                                               $this->dieWithError(
-                                                       [ 'apierror-contentserializationexception', wfEscapeWikiText( $ex->getMessage() ) ],
-                                                       'parseerror'
-                                               );
+                                               $this->dieWithException( $ex, [
+                                                       'wrap' => ApiMessage::create( 'apierror-contentserializationexception', 'parseerror' )
+                                               ] );
                                                return;
                                        }
                                } else {
@@ -443,35 +441,62 @@ class ApiEditPage extends ApiBase {
                                break;
 
                        default:
-                               // EditPage sometimes only sets the status code without setting
-                               // any actual error messages. Supply defaults for those cases.
-                               $maxArticleSize = $this->getConfig()->get( 'MaxArticleSize' );
-                               $defaultMessages = [
-                                       // Currently needed
-                                       EditPage::AS_IMAGE_REDIRECT_ANON => [ 'apierror-noimageredirect-anon' ],
-                                       EditPage::AS_IMAGE_REDIRECT_LOGGED => [ 'apierror-noimageredirect-logged' ],
-                                       EditPage::AS_CONTENT_TOO_BIG => [ 'apierror-contenttoobig', $maxArticleSize ],
-                                       EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED => [ 'apierror-contenttoobig', $maxArticleSize ],
-                                       EditPage::AS_READ_ONLY_PAGE_ANON => [ 'apierror-noedit-anon' ],
-                                       EditPage::AS_NO_CHANGE_CONTENT_MODEL => [ 'apierror-cantchangecontentmodel' ],
-                                       EditPage::AS_ARTICLE_WAS_DELETED => [ 'apierror-pagedeleted' ],
-                                       EditPage::AS_CONFLICT_DETECTED => [ 'editconflict' ],
-
-                                       // Currently shouldn't be needed
-                                       EditPage::AS_SPAM_ERROR => [ 'apierror-spamdetected', wfEscapeWikiText( $result['spam'] ) ],
-                                       EditPage::AS_READ_ONLY_PAGE_LOGGED => [ 'apierror-noedit' ],
-                                       EditPage::AS_RATE_LIMITED => [ 'apierror-ratelimited' ],
-                                       EditPage::AS_NO_CREATE_PERMISSION => [ 'nocreate-loggedin' ],
-                                       EditPage::AS_BLANK_ARTICLE => [ 'apierror-emptypage' ],
-                                       EditPage::AS_TEXTBOX_EMPTY => [ 'apierror-emptynewsection' ],
-                                       EditPage::AS_SUMMARY_NEEDED => [ 'apierror-summaryrequired' ],
-                               ];
                                if ( !$status->getErrors() ) {
-                                       if ( isset( $defaultMessages[$status->value] ) ) {
-                                               call_user_func_array( [ $status, 'fatal' ], $defaultMessages[$status->value] );
-                                       } else {
-                                               wfWarn( __METHOD__ . ": Unknown EditPage code {$status->value} with no message" );
-                                               $status->fatal( 'apierror-unknownerror-editpage', $status->value );
+                                       // EditPage sometimes only sets the status code without setting
+                                       // any actual error messages. Supply defaults for those cases.
+                                       switch ( $status->value ) {
+                                               // Currently needed
+                                               case EditPage::AS_IMAGE_REDIRECT_ANON:
+                                                       $status->fatal( 'apierror-noimageredirect-anon' );
+                                                       break;
+                                               case EditPage::AS_IMAGE_REDIRECT_LOGGED:
+                                                       $status->fatal( 'apierror-noimageredirect-logged' );
+                                                       break;
+                                               case EditPage::AS_CONTENT_TOO_BIG:
+                                               case EditPage::AS_MAX_ARTICLE_SIZE_EXCEEDED:
+                                                       $status->fatal( 'apierror-contenttoobig', $this->getConfig()->get( 'MaxArticleSize' ) );
+                                                       break;
+                                               case EditPage::AS_READ_ONLY_PAGE_ANON:
+                                                       $status->fatal( 'apierror-noedit-anon' );
+                                                       break;
+                                               case EditPage::AS_NO_CHANGE_CONTENT_MODEL:
+                                                       $status->fatal( 'apierror-cantchangecontentmodel' );
+                                                       break;
+                                               case EditPage::AS_ARTICLE_WAS_DELETED:
+                                                       $status->fatal( 'apierror-pagedeleted' );
+                                                       break;
+                                               case EditPage::AS_CONFLICT_DETECTED:
+                                                       $status->fatal( 'editconflict' );
+                                                       break;
+
+                                               // Currently shouldn't be needed, but here in case
+                                               // hooks use them without setting appropriate
+                                               // errors on the status.
+                                               case EditPage::AS_SPAM_ERROR:
+                                                       $status->fatal( 'apierror-spamdetected', $result['spam'] );
+                                                       break;
+                                               case EditPage::AS_READ_ONLY_PAGE_LOGGED:
+                                                       $status->fatal( 'apierror-noedit' );
+                                                       break;
+                                               case EditPage::AS_RATE_LIMITED:
+                                                       $status->fatal( 'apierror-ratelimited' );
+                                                       break;
+                                               case EditPage::AS_NO_CREATE_PERMISSION:
+                                                       $status->fatal( 'nocreate-loggedin' );
+                                                       break;
+                                               case EditPage::AS_BLANK_ARTICLE:
+                                                       $status->fatal( 'apierror-emptypage' );
+                                                       break;
+                                               case EditPage::AS_TEXTBOX_EMPTY:
+                                                       $status->fatal( 'apierror-emptynewsection' );
+                                                       break;
+                                               case EditPage::AS_SUMMARY_NEEDED:
+                                                       $status->fatal( 'apierror-summaryrequired' );
+                                                       break;
+                                               default:
+                                                       wfWarn( __METHOD__ . ": Unknown EditPage code {$status->value} with no message" );
+                                                       $status->fatal( 'apierror-unknownerror-editpage', $status->value );
+                                                       break;
                                        }
                                }
                                $this->dieStatus( $status );
index 4fb19b8..814004a 100644 (file)
@@ -142,6 +142,67 @@ class ApiErrorFormatter {
                }
        }
 
+       /**
+        * Get an ApiMessage from an exception
+        * @since 1.29
+        * @param Exception|Throwable $exception
+        * @param array $options
+        *  - wrap: (string|array|MessageSpecifier) Used to wrap the exception's
+        *    message if it's not an ILocalizedException. The exception's message
+        *    will be added as the final parameter.
+        *  - code: (string) Default code
+        *  - data: (array) Default extra data
+        * @return IApiMessage
+        */
+       public function getMessageFromException( $exception, array $options = [] ) {
+               $options += [ 'code' => null, 'data' => [] ];
+
+               if ( $exception instanceof ILocalizedException ) {
+                       $msg = $exception->getMessageObject();
+                       $params = [];
+               } else {
+                       // Extract code and data from the exception, if applicable
+                       if ( $exception instanceof UsageException ) {
+                               $data = $exception->getMessageArray();
+                               if ( !$options['code'] ) {
+                                       $options['code'] = $data['code'];
+                               }
+                               unset( $data['code'], $data['info'] );
+                               $options['data'] = array_merge( $data, $options['data'] );
+                       }
+
+                       if ( isset( $options['wrap'] ) ) {
+                               $msg = $options['wrap'];
+                       } else {
+                               $msg = new RawMessage( '$1' );
+                               if ( !isset( $options['code'] ) ) {
+                                       $options['code'] = 'internal_api_error_' . get_class( $exception );
+                               }
+                       }
+                       $params = [ wfEscapeWikiText( $exception->getMessage() ) ];
+               }
+               return ApiMessage::create( $msg, $options['code'], $options['data'] )
+                       ->params( $params )
+                       ->inLanguage( $this->lang )
+                       ->title( $this->getDummyTitle() )
+                       ->useDatabase( $this->useDB );
+       }
+
+       /**
+        * Format an exception as an array
+        * @since 1.29
+        * @param Exception|Throwable $exception
+        * @param array $options See self::getMessageFromException(), plus
+        *  - format: (string) Format override
+        * @return array
+        */
+       public function formatException( $exception, array $options = [] ) {
+               return $this->formatMessage(
+                       $this->getMessageFromException( $exception, $options ),
+                       isset( $options['format'] ) ? $options['format'] : null
+               );
+       }
+
        /**
         * Format a message as an array
         * @param Message|array|string $msg Message. See ApiMessage::create().
@@ -335,6 +396,19 @@ class ApiErrorFormatter_BackCompat extends ApiErrorFormatter {
                ] + $msg->getApiData();
        }
 
+       /**
+        * Format an exception as an array
+        * @since 1.29
+        * @param Exception|Throwable $exception
+        * @param array $options See parent::formatException(), plus
+        *  - bc: (bool) Return only the string, not an array
+        * @return array|string
+        */
+       public function formatException( $exception, array $options = [] ) {
+               $ret = parent::formatException( $exception, $options );
+               return empty( $options['bc'] ) ? $ret : $ret['info'];
+       }
+
        protected function addWarningOrError( $tag, $modulePath, $msg ) {
                $value = self::stripMarkup( $msg->text() );
 
index 2a6c938..9a0d3ff 100644 (file)
@@ -90,7 +90,6 @@ class ApiHelp extends ApiBase {
         * @param IContextSource $context
         * @param ApiBase[]|ApiBase $modules
         * @param array $options Formatting options (described above)
-        * @return string
         */
        public static function getHelp( IContextSource $context, $modules, array $options ) {
                global $wgContLang;
index 3f48f38..dffd6b2 100644 (file)
@@ -83,7 +83,7 @@ class ApiImport extends ApiBase {
                try {
                        $importer->doImport();
                } catch ( Exception $e ) {
-                       $this->dieWithError( [ 'apierror-import-unknownerror', wfEscapeWikiText( $e->getMessage() ) ] );
+                       $this->dieWithException( $e, [ 'wrap' => 'apierror-import-unknownerror' ] );
                }
 
                $resultData = $reporter->getData();
index fe6ed41..4220fb8 100644 (file)
@@ -79,6 +79,7 @@ class ApiMain extends ApiBase {
                'tokens' => 'ApiTokens',
                'checktoken' => 'ApiCheckToken',
                'cspreport' => 'ApiCSPReport',
+               'validatepassword' => 'ApiValidatePassword',
 
                // Write modules
                'purge' => 'ApiPurge',
@@ -1046,7 +1047,9 @@ class ApiMain extends ApiBase {
                                $params = [
                                        'apierror-exceptioncaught',
                                        WebRequest::getRequestId(),
-                                       wfEscapeWikiText( $e->getMessage() )
+                                       $e instanceof ILocalizedException
+                                               ? $e->getMessageObject()
+                                               : wfEscapeWikiText( $e->getMessage() )
                                ];
                        }
                        $messages[] = ApiMessage::create( $params, $code );
index 9d69a77..9e42d5f 100644 (file)
@@ -126,6 +126,7 @@ trait ApiMessageTrait {
                'rcpatroldisabled' => 'patroldisabled',
                'readonlytext' => 'readonly',
                'sessionfailure' => 'badtoken',
+               'systemblockedtext' => 'blocked',
                'titleprotected' => 'protectedtitle',
                'undo-failure' => 'undofailure',
                'userrights-nodatabase' => 'nosuchdatabase',
index 7c8aa90..18e582d 100644 (file)
@@ -59,7 +59,7 @@ class ApiMove extends ApiBase {
                if ( !$toTitle || $toTitle->isExternal() ) {
                        $this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['to'] ) ] );
                }
-               $toTalk = $toTitle->getTalkPage();
+               $toTalk = $toTitle->canTalk() ? $toTitle->getTalkPage() : null;
 
                if ( $toTitle->getNamespace() == NS_FILE
                        && !RepoGroup::singleton()->getLocalRepo()->findFile( $toTitle )
@@ -100,7 +100,7 @@ class ApiMove extends ApiBase {
                $r['moveoverredirect'] = $toTitleExists;
 
                // Move the talk page
-               if ( $params['movetalk'] && $fromTalk->exists() && !$fromTitle->isTalkPage() ) {
+               if ( $params['movetalk'] && $toTalk && $fromTalk->exists() && !$fromTitle->isTalkPage() ) {
                        $toTalkExists = $toTalk->exists();
                        $status = $this->movePage( $fromTalk, $toTalk, $params['reason'], !$params['noredirect'] );
                        if ( $status->isOK() ) {
index 4cf896f..160ce87 100644 (file)
@@ -1151,7 +1151,7 @@ class ApiPageSet extends ApiBase {
                                        $this->mAllPages[0][$title] = $this->mFakePageId;
                                        $this->mInvalidTitles[$this->mFakePageId] = [
                                                'title' => $title,
-                                               'invalidreason' => $ex->getMessage(),
+                                               'invalidreason' => $this->getErrorFormatter()->formatException( $ex, [ 'bc' => true ] ),
                                        ];
                                        $this->mFakePageId--;
                                        continue; // There's nothing else we can do
index a9b3dde..46ba34b 100644 (file)
@@ -237,7 +237,7 @@ class ApiParamInfo extends ApiBase {
 
        /**
         * @param ApiBase $module
-        * @return ApiResult
+        * @return array
         */
        private function getModuleInfo( $module ) {
                $ret = [];
index 2263b8f..287ffb7 100644 (file)
@@ -225,11 +225,9 @@ class ApiParse extends ApiBase {
                        try {
                                $this->content = ContentHandler::makeContent( $text, $titleObj, $model, $format );
                        } catch ( MWContentSerializationException $ex ) {
-                               // @todo: Internationalize MWContentSerializationException
-                               $this->dieWithError(
-                                       [ 'apierror-contentserializationexception', wfEscapeWikiText( $ex->getMessage() ) ],
-                                       'parseerror'
-                               );
+                               $this->dieWithException( $ex, [
+                                       'wrap' => ApiMessage::create( 'apierror-contentserializationexception', 'parseerror' )
+                               ] );
                        }
 
                        if ( $this->section !== false ) {
index af2aed5..281fb61 100644 (file)
@@ -584,7 +584,7 @@ abstract class ApiQueryBase extends ApiBase {
         * @return bool
         */
        public function validateSha1Hash( $hash ) {
-               return preg_match( '/^[a-f0-9]{40}$/', $hash );
+               return (bool)preg_match( '/^[a-f0-9]{40}$/', $hash );
        }
 
        /**
@@ -592,7 +592,7 @@ abstract class ApiQueryBase extends ApiBase {
         * @return bool
         */
        public function validateSha1Base36Hash( $hash ) {
-               return preg_match( '/^[a-z0-9]{31}$/', $hash );
+               return (bool)preg_match( '/^[a-z0-9]{31}$/', $hash );
        }
 
        /**
index 02961aa..3a8847c 100644 (file)
@@ -53,7 +53,7 @@ class ApiQueryCategoryMembers extends ApiQueryGeneratorBase {
         */
        private function validateHexSortkey( $hexSortkey ) {
                // A hex sortkey has an unbound number of 2 letter pairs
-               return preg_match( '/^(?:[a-fA-F0-9]{2})*$/D', $hexSortkey );
+               return (bool)preg_match( '/^(?:[a-fA-F0-9]{2})*$/D', $hexSortkey );
        }
 
        /**
index 0bbfad3..c9dae8d 100644 (file)
@@ -58,6 +58,15 @@ class ApiQueryImageInfo extends ApiQueryBase {
                        'revdelUser' => $this->getUser(),
                ];
 
+               if ( isset( $params['badfilecontexttitle'] ) ) {
+                       $badFileContextTitle = Title::newFromText( $params['badfilecontexttitle'] );
+                       if ( !$badFileContextTitle ) {
+                               $this->dieUsage( 'Invalid title in badfilecontexttitle parameter', 'invalid-title' );
+                       }
+               } else {
+                       $badFileContextTitle = false;
+               }
+
                $pageIds = $this->getPageSet()->getGoodAndMissingTitlesByNamespace();
                if ( !empty( $pageIds[NS_FILE] ) ) {
                        $titles = array_keys( $pageIds[NS_FILE] );
@@ -95,13 +104,16 @@ class ApiQueryImageInfo extends ApiQueryBase {
 
                        $result = $this->getResult();
                        foreach ( $titles as $title ) {
+                               $info = [];
                                $pageId = $pageIds[NS_FILE][$title];
                                $start = $title === $fromTitle ? $fromTimestamp : $params['start'];
 
                                if ( !isset( $images[$title] ) ) {
-                                       if ( isset( $prop['uploadwarning'] ) ) {
-                                               // Uploadwarning needs info about non-existing files
+                                       if ( isset( $prop['uploadwarning'] ) || isset( $prop['badfile'] ) ) {
+                                               // uploadwarning and badfile need info about non-existing files
                                                $images[$title] = wfLocalFile( $title );
+                                               // Doesn't exist, so set an empty image repository
+                                               $info['imagerepository'] = '';
                                        } else {
                                                $result->addValue(
                                                        [ 'query', 'pages', intval( $pageId ) ],
@@ -128,10 +140,14 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                        break;
                                }
 
-                               $fit = $result->addValue(
-                                       [ 'query', 'pages', intval( $pageId ) ],
-                                       'imagerepository', $img->getRepoName()
-                               );
+                               if ( !isset( $info['imagerepository'] ) ) {
+                                       $info['imagerepository'] = $img->getRepoName();
+                               }
+                               if ( isset( $prop['badfile'] ) ) {
+                                       $info['badfile'] = (bool)wfIsBadImage( $title, $badFileContextTitle );
+                               }
+
+                               $fit = $result->addValue( [ 'query', 'pages' ], intval( $pageId ), $info );
                                if ( !$fit ) {
                                        if ( count( $pageIds[NS_FILE] ) == 1 ) {
                                                // The user is screwed. imageinfo can't be solely
@@ -688,6 +704,9 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                ApiBase::PARAM_DFLT => '',
                                ApiBase::PARAM_TYPE => 'string',
                        ],
+                       'badfilecontexttitle' => [
+                               ApiBase::PARAM_TYPE => 'string',
+                       ],
                        'continue' => [
                                ApiBase::PARAM_HELP_MSG => 'api-help-param-continue',
                        ],
@@ -733,6 +752,7 @@ class ApiQueryImageInfo extends ApiQueryBase {
                                'archivename' => 'apihelp-query+imageinfo-paramvalue-prop-archivename',
                                'bitdepth' => 'apihelp-query+imageinfo-paramvalue-prop-bitdepth',
                                'uploadwarning' => 'apihelp-query+imageinfo-paramvalue-prop-uploadwarning',
+                               'badfile' => 'apihelp-query+imageinfo-paramvalue-prop-badfile',
                        ],
                        array_flip( $filter )
                );
index 64bc43f..05b693d 100644 (file)
@@ -175,119 +175,44 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                                continue;
                        }
 
-                       $title = $result->getTitle();
                        if ( $resultPageSet === null ) {
-                               $vals = [];
-                               ApiQueryBase::addTitleInfo( $vals, $title );
-
-                               if ( isset( $prop['snippet'] ) ) {
-                                       $vals['snippet'] = $result->getTextSnippet( $terms );
-                               }
-                               if ( isset( $prop['size'] ) ) {
-                                       $vals['size'] = $result->getByteSize();
-                               }
-                               if ( isset( $prop['wordcount'] ) ) {
-                                       $vals['wordcount'] = $result->getWordCount();
-                               }
-                               if ( isset( $prop['timestamp'] ) ) {
-                                       $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $result->getTimestamp() );
-                               }
-                               if ( isset( $prop['titlesnippet'] ) ) {
-                                       $vals['titlesnippet'] = $result->getTitleSnippet();
-                               }
-                               if ( isset( $prop['categorysnippet'] ) ) {
-                                       $vals['categorysnippet'] = $result->getCategorySnippet();
-                               }
-                               if ( !is_null( $result->getRedirectTitle() ) ) {
-                                       if ( isset( $prop['redirecttitle'] ) ) {
-                                               $vals['redirecttitle'] = $result->getRedirectTitle()->getPrefixedText();
-                                       }
-                                       if ( isset( $prop['redirectsnippet'] ) ) {
-                                               $vals['redirectsnippet'] = $result->getRedirectSnippet();
+                               $vals = $this->getSearchResultData( $result, $prop, $terms );
+                               if ( $vals ) {
+                                       // Add item to results and see whether it fits
+                                       $fit = $apiResult->addValue( [ 'query', $this->getModuleName() ], null, $vals );
+                                       if ( !$fit ) {
+                                               $this->setContinueEnumParameter( 'offset', $params['offset'] + $count - 1 );
+                                               break;
                                        }
                                }
-                               if ( !is_null( $result->getSectionTitle() ) ) {
-                                       if ( isset( $prop['sectiontitle'] ) ) {
-                                               $vals['sectiontitle'] = $result->getSectionTitle()->getFragment();
-                                       }
-                                       if ( isset( $prop['sectionsnippet'] ) ) {
-                                               $vals['sectionsnippet'] = $result->getSectionSnippet();
-                                       }
-                               }
-                               if ( isset( $prop['isfilematch'] ) ) {
-                                       $vals['isfilematch'] = $result->isFileMatch();
-                               }
-
-                               // Add item to results and see whether it fits
-                               $fit = $apiResult->addValue( [ 'query', $this->getModuleName() ],
-                                       null, $vals );
-                               if ( !$fit ) {
-                                       $this->setContinueEnumParameter( 'offset', $params['offset'] + $count - 1 );
-                                       break;
-                               }
                        } else {
-                               $titles[] = $title;
+                               $titles[] = $result->getTitle();
                        }
 
                        $result = $matches->next();
                }
 
-               $hasInterwikiResults = false;
-               $totalhits = null;
-               if ( $interwiki && $resultPageSet === null && $matches->hasInterwikiResults() ) {
-                       foreach ( $matches->getInterwikiResults() as $interwikiMatches ) {
-                               $hasInterwikiResults = true;
-
-                               // Include number of results if requested
-                               if ( $resultPageSet === null && isset( $searchInfo['totalhits'] ) ) {
-                                       $totalhits += $interwikiMatches->getTotalHits();
-                               }
-
-                               $result = $interwikiMatches->next();
-                               while ( $result ) {
-                                       $title = $result->getTitle();
-
-                                       if ( $resultPageSet === null ) {
-                                               $vals = [
-                                                       'namespace' => $result->getInterwikiNamespaceText(),
-                                                       'title' => $title->getText(),
-                                                       'url' => $title->getFullURL(),
-                                               ];
-
-                                               // Add item to results and see whether it fits
-                                               $fit = $apiResult->addValue(
-                                                       [ 'query', 'interwiki' . $this->getModuleName(), $result->getInterwikiPrefix() ],
-                                                       null,
-                                                       $vals
-                                               );
-
-                                               if ( !$fit ) {
-                                                       // We hit the limit. We can't really provide any meaningful
-                                                       // pagination info so just bail out
-                                                       break;
-                                               }
-                                       } else {
-                                               $titles[] = $title;
-                                       }
+               // Here we assume interwiki results do not count with
+               // regular search results. We may want to reconsider this
+               // if we ever return a lot of interwiki results or want pagination
+               // for them.
+               // Interwiki results inside main result set
+               $canAddInterwiki = (bool)$params['enablerewrites'] && ( $resultPageSet === null );
+               if ( $canAddInterwiki ) {
+                       $this->addInterwikiResults( $matches, $apiResult, $prop, $terms, 'additional',
+                               SearchResultSet::INLINE_RESULTS );
+               }
 
-                                       $result = $interwikiMatches->next();
-                               }
-                       }
-                       if ( $totalhits !== null ) {
-                               $apiResult->addValue( [ 'query', 'interwikisearchinfo' ],
-                                       'totalhits', $totalhits );
-                       }
+               // Interwiki results outside main result set
+               if ( $interwiki && $resultPageSet === null ) {
+                       $this->addInterwikiResults( $matches, $apiResult, $prop, $terms, 'interwiki',
+                               SearchResultSet::SECONDARY_RESULTS );
                }
 
                if ( $resultPageSet === null ) {
                        $apiResult->addIndexedTagName( [
                                'query', $this->getModuleName()
                        ], 'p' );
-                       if ( $hasInterwikiResults ) {
-                               $apiResult->addIndexedTagName( [
-                                       'query', 'interwiki' . $this->getModuleName()
-                               ], 'p' );
-                       }
                } else {
                        $resultPageSet->setRedirectMergePolicy( function ( $current, $new ) {
                                if ( !isset( $current['index'] ) || $new['index'] < $current['index'] ) {
@@ -303,6 +228,119 @@ class ApiQuerySearch extends ApiQueryGeneratorBase {
                }
        }
 
+       /**
+        * Assemble search result data.
+        * @param SearchResult $result Search result
+        * @param array        $prop Props to extract (as keys)
+        * @param array        $terms Terms list
+        * @return array|null Result data or null if result is broken in some way.
+        */
+       private function getSearchResultData( SearchResult $result, $prop, $terms ) {
+               // Silently skip broken and missing titles
+               if ( $result->isBrokenTitle() || $result->isMissingRevision() ) {
+                       return null;
+               }
+
+               $vals = [];
+
+               $title = $result->getTitle();
+               ApiQueryBase::addTitleInfo( $vals, $title );
+
+               if ( isset( $prop['size'] ) ) {
+                       $vals['size'] = $result->getByteSize();
+               }
+               if ( isset( $prop['wordcount'] ) ) {
+                       $vals['wordcount'] = $result->getWordCount();
+               }
+               if ( isset( $prop['snippet'] ) ) {
+                       $vals['snippet'] = $result->getTextSnippet( $terms );
+               }
+               if ( isset( $prop['timestamp'] ) ) {
+                       $vals['timestamp'] = wfTimestamp( TS_ISO_8601, $result->getTimestamp() );
+               }
+               if ( isset( $prop['titlesnippet'] ) ) {
+                       $vals['titlesnippet'] = $result->getTitleSnippet();
+               }
+               if ( isset( $prop['categorysnippet'] ) ) {
+                       $vals['categorysnippet'] = $result->getCategorySnippet();
+               }
+               if ( !is_null( $result->getRedirectTitle() ) ) {
+                       if ( isset( $prop['redirecttitle'] ) ) {
+                               $vals['redirecttitle'] = $result->getRedirectTitle()->getPrefixedText();
+                       }
+                       if ( isset( $prop['redirectsnippet'] ) ) {
+                               $vals['redirectsnippet'] = $result->getRedirectSnippet();
+                       }
+               }
+               if ( !is_null( $result->getSectionTitle() ) ) {
+                       if ( isset( $prop['sectiontitle'] ) ) {
+                               $vals['sectiontitle'] = $result->getSectionTitle()->getFragment();
+                       }
+                       if ( isset( $prop['sectionsnippet'] ) ) {
+                               $vals['sectionsnippet'] = $result->getSectionSnippet();
+                       }
+               }
+               if ( isset( $prop['isfilematch'] ) ) {
+                       $vals['isfilematch'] = $result->isFileMatch();
+               }
+               return $vals;
+       }
+
+       /**
+        * Add interwiki results as a section in query results.
+        * @param SearchResultSet $matches
+        * @param ApiResult       $apiResult
+        * @param array           $prop Props to extract (as keys)
+        * @param array           $terms Terms list
+        * @param string          $section Section name where results would go
+        * @param int             $type Interwiki result type
+        * @return int|null Number of total hits in the data or null if none was produced
+        */
+       private function addInterwikiResults(
+               SearchResultSet $matches, ApiResult $apiResult, $prop,
+               $terms, $section, $type
+       ) {
+               $totalhits = null;
+               if ( $matches->hasInterwikiResults( $type ) ) {
+                       foreach ( $matches->getInterwikiResults( $type ) as $interwikiMatches ) {
+                               // Include number of results if requested
+                               $totalhits += $interwikiMatches->getTotalHits();
+
+                               $result = $interwikiMatches->next();
+                               while ( $result ) {
+                                       $title = $result->getTitle();
+                                       $vals = $this->getSearchResultData( $result, $prop, $terms );
+
+                                       $vals['namespace'] = $result->getInterwikiNamespaceText();
+                                       $vals['title'] = $title->getText();
+                                       $vals['url'] = $title->getFullURL();
+
+                                       // Add item to results and see whether it fits
+                                       $fit = $apiResult->addValue( [
+                                                       'query',
+                                                       $section . $this->getModuleName(),
+                                                       $result->getInterwikiPrefix()
+                                               ], null, $vals );
+
+                                       if ( !$fit ) {
+                                               // We hit the limit. We can't really provide any meaningful
+                                               // pagination info so just bail out
+                                               break;
+                                       }
+
+                                       $result = $interwikiMatches->next();
+                               }
+                       }
+                       if ( $totalhits !== null ) {
+                               $apiResult->addValue( [ 'query', $section . 'searchinfo' ], 'totalhits', $totalhits );
+                               $apiResult->addIndexedTagName( [
+                                       'query', $section . $this->getModuleName()
+                               ], 'p' );
+                       }
+               }
+               return $totalhits;
+       }
+
        public function getCacheMode( $params ) {
                return 'public';
        }
index 981cb09..abb827f 100644 (file)
@@ -63,11 +63,10 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
                                $result->addIndexedTagName( [ 'query', $this->getModuleName() ], $modulePrefix );
                        }
                // @todo Update exception handling here to understand current getFile exceptions
-               // @todo Internationalize the exceptions
                } catch ( UploadStashFileNotFoundException $e ) {
-                       $this->dieWithError( [ 'apierror-stashedfilenotfound', wfEscapeWikiText( $e->getMessage() ) ] );
+                       $this->dieWithException( $e, [ 'wrap' => 'apierror-stashedfilenotfound' ] );
                } catch ( UploadStashBadPathException $e ) {
-                       $this->dieWithError( [ 'apierror-stashpathinvalid', wfEscapeWikiText( $e->getMessage() ) ] );
+                       $this->dieWithException( $e, [ 'wrap' => 'apierror-stashpathinvalid' ] );
                }
        }
 
index 3b60478..60e122c 100644 (file)
@@ -64,6 +64,7 @@ class ApiQueryUserInfo extends ApiQueryBase {
         *  - blockreason - reason provided for the block
         *  - blockedtimestamp - timestamp for when the block was placed/modified
         *  - blockexpiry - expiry time of the block
+        *  - systemblocktype - system block type, if any
         */
        public static function getBlockInfo( Block $block ) {
                global $wgContLang;
@@ -76,6 +77,9 @@ class ApiQueryUserInfo extends ApiQueryBase {
                $vals['blockexpiry'] = $wgContLang->formatExpiry(
                        $block->getExpiry(), TS_ISO_8601, 'infinite'
                );
+               if ( $block->getSystemBlockType() !== null ) {
+                       $vals['systemblocktype'] = $block->getSystemBlockType();
+               }
                return $vals;
        }
 
index 6b5ceb7..3f59751 100644 (file)
@@ -151,7 +151,10 @@ class ApiQueryWatchlist extends ApiQueryGeneratorBase {
 
                if ( !is_null( $params['type'] ) ) {
                        try {
-                               $options['rcTypes'] = RecentChange::parseToRCType( $params['type'] );
+                               $rcTypes = RecentChange::parseToRCType( $params['type'] );
+                               if ( $rcTypes ) {
+                                       $options['rcTypes'] = $rcTypes;
+                               }
                        } catch ( Exception $e ) {
                                ApiBase::dieDebug( __METHOD__, $e->getMessage() );
                        }
index e29fda5..37ee3e7 100644 (file)
@@ -168,7 +168,7 @@ class ApiStashEdit extends ApiBase {
         * @param Content $content Edit content
         * @param User $user
         * @param string $summary Edit summary
-        * @return integer ApiStashEdit::ERROR_* constant
+        * @return string ApiStashEdit::ERROR_* constant
         * @since 1.25
         */
        public static function parseAndStash( WikiPage $page, Content $content, User $user, $summary ) {
index f6c0584..b142900 100644 (file)
@@ -109,7 +109,7 @@ class ApiTag extends ApiBase {
                } else {
                        $idResult['status'] = 'success';
                        if ( is_null( $status->value->logId ) ) {
-                               $idResult['noop'] = '';
+                               $idResult['noop'] = true;
                        } else {
                                $idResult['actionlogid'] = $status->value->logId;
                                $idResult['added'] = $status->value->addedTags;
index 6bdd68f..311fa54 100644 (file)
@@ -320,12 +320,14 @@ class ApiUpload extends ApiBase {
 
                        if ( $status->isGood() && !$status->getValue() ) {
                                // Not actually a 'good' status...
-                               $status->fatal( new ApiRawMessage( 'Invalid stashed file', 'stashfailed' ) );
+                               $status->fatal( new ApiMessage( 'apierror-stashinvalidfile', 'stashfailed' ) );
                        }
                } catch ( Exception $e ) {
                        $debugMessage = 'Stashing temporary file failed: ' . get_class( $e ) . ' ' . $e->getMessage();
                        wfDebug( __METHOD__ . ' ' . $debugMessage . "\n" );
-                       $status = Status::newFatal( new ApiRawMessage( $e->getMessage(), 'stashfailed' ) );
+                       $status = Status::newFatal( $this->getErrorFormatter()->getMessageFromException(
+                               $e, [ 'wrap' => new ApiMessage( 'apierror-stashexception', 'stashfailed' ) ]
+                       ) );
                }
 
                if ( $status->isGood() ) {
@@ -564,7 +566,6 @@ class ApiUpload extends ApiBase {
         * @param array $verification
         */
        protected function checkVerification( array $verification ) {
-               // @todo Move them to ApiBase's message map
                switch ( $verification['status'] ) {
                        // Recoverable errors
                        case UploadBase::MIN_LENGTH_PARTNAME:
@@ -713,32 +714,41 @@ class ApiUpload extends ApiBase {
 
        /**
         * Handles a stash exception, giving a useful error to the user.
-        * @todo Internationalize the exceptions
+        * @todo Internationalize the exceptions then get rid of this
         * @param Exception $e
         * @return StatusValue
         */
        protected function handleStashException( $e ) {
-               $err = wfEscapeWikiText( $e->getMessage() );
                switch ( get_class( $exception ) ) {
                        case 'UploadStashFileNotFoundException':
-                               return StatusValue::newFatal( 'apierror-stashedfilenotfound', $err );
+                               $wrap = 'apierror-stashedfilenotfound';
+                               break;
                        case 'UploadStashBadPathException':
-                               return StatusValue::newFatal( 'apierror-stashpathinvalid', $err );
+                               $wrap = 'apierror-stashpathinvalid';
+                               break;
                        case 'UploadStashFileException':
-                               return StatusValue::newFatal( 'apierror-stashfilestorage', $err );
+                               $wrap = 'apierror-stashfilestorage';
+                               break;
                        case 'UploadStashZeroLengthFileException':
-                               return StatusValue::newFatal( 'apierror-stashzerolength', $err );
+                               $wrap = 'apierror-stashzerolength';
+                               break;
                        case 'UploadStashNotLoggedInException':
                                return StatusValue::newFatal( ApiMessage::create(
                                        [ 'apierror-mustbeloggedin', $this->msg( 'action-upload' ) ], 'stashnotloggedin'
                                ) );
                        case 'UploadStashWrongOwnerException':
-                               return StatusValue::newFatal( 'apierror-stashwrongowner', $err );
+                               $wrap = 'apierror-stashwrongowner';
+                               break;
                        case 'UploadStashNoSuchKeyException':
-                               return StatusValue::newFatal( 'apierror-stashnosuchfilekey', $err );
+                               $wrap = 'apierror-stashnosuchfilekey';
+                               break;
                        default:
-                               return StatusValue::newFatal( 'uploadstash-exception', get_class( $e ), $err );
+                               $wrap = [ 'uploadstash-exception', get_class( $e ) ];
+                               break;
                }
+               return StatusValue::newFatal(
+                       $this->getErrorFormatter()->getMessageFromException( $e, [ 'wrap' => $wrap ] )
+               );
        }
 
        /**
index 7e21ab5..9dc1f92 100644 (file)
@@ -95,7 +95,7 @@ class UsageException extends MWException {
  *  starts throwing ApiUsageException. Eventually UsageException will go away
  *  and this will (probably) extend MWException directly.
  */
-class ApiUsageException extends UsageException {
+class ApiUsageException extends UsageException implements ILocalizedException {
 
        protected $modulePath;
        protected $status;
@@ -201,6 +201,13 @@ class ApiUsageException extends UsageException {
                ] + $enMsg->getApiData();
        }
 
+       /**
+        * @inheritdoc
+        */
+       public function getMessageObject() {
+               return $this->status->getMessage();
+       }
+
        /**
         * @return string
         */
diff --git a/includes/api/ApiValidatePassword.php b/includes/api/ApiValidatePassword.php
new file mode 100644 (file)
index 0000000..6968523
--- /dev/null
@@ -0,0 +1,81 @@
+<?php
+
+use MediaWiki\Auth\AuthManager;
+
+/**
+ * @ingroup API
+ */
+class ApiValidatePassword extends ApiBase {
+
+       public function execute() {
+               $params = $this->extractRequestParams();
+
+               // For sanity
+               $this->requirePostedParameters( [ 'password' ] );
+
+               if ( $params['user'] !== null ) {
+                       $user = User::newFromName( $params['user'], 'creatable' );
+                       if ( !$user ) {
+                               $encParamName = $this->encodeParamName( 'user' );
+                               $this->dieWithError(
+                                       [ 'apierror-baduser', $encParamName, wfEscapeWikiText( $params['user'] ) ],
+                                       "baduser_{$encParamName}"
+                               );
+                       }
+
+                       if ( !$user->isAnon() || AuthManager::singleton()->userExists( $user->getName() ) ) {
+                               $this->dieWithError( 'userexists' );
+                       }
+
+                       $user->setEmail( (string)$params['email'] );
+                       $user->setRealName( (string)$params['realname'] );
+               } else {
+                       $user = $this->getUser();
+               }
+
+               $validity = $user->checkPasswordValidity( $params['password'] );
+               $r['validity'] = $validity->isGood() ? 'Good' : ( $validity->isOK() ? 'Change' : 'Invalid' );
+               $messages = array_merge(
+                       $this->getErrorFormatter()->arrayFromStatus( $validity, 'error' ),
+                       $this->getErrorFormatter()->arrayFromStatus( $validity, 'warning' )
+               );
+               if ( $messages ) {
+                       $r['validitymessages'] = $messages;
+               }
+
+               Hooks::run( 'ApiValidatePassword', [ $this, &$r ] );
+
+               $this->getResult()->addValue( null, $this->getModuleName(), $r );
+       }
+
+       public function mustBePosted() {
+               return true;
+       }
+
+       public function getAllowedParams() {
+               return [
+                       'password' => [
+                               ApiBase::PARAM_TYPE => 'password',
+                               ApiBase::PARAM_REQUIRED => true
+                       ],
+                       'user' => [
+                               ApiBase::PARAM_TYPE => 'user',
+                       ],
+                       'email' => null,
+                       'realname' => null,
+               ];
+       }
+
+       protected function getExamplesMessages() {
+               return [
+                       'action=validatepassword&password=foobar'
+                               => 'apihelp-validatepassword-example-1',
+                       'action=validatepassword&password=querty&user=Example'
+                               => 'apihelp-validatepassword-example-2',
+               ];
+       }
+
+       public function getHelpUrls() {
+               return 'https://www.mediawiki.org/wiki/API:Validatepassword';
+       }
+}
index 88aff41..37d319f 100644 (file)
@@ -60,7 +60,7 @@ class ApiWatch extends ApiBase {
 
                        foreach ( $pageSet->getMissingTitles() as $title ) {
                                $r = $this->watchTitle( $title, $user, $params );
-                               $r['missing'] = 1;
+                               $r['missing'] = true;
                                $res[] = $r;
                        }
 
index 03c9f52..86078d4 100644 (file)
                        "Fatz",
                        "Hiba Alshawi",
                        "Maroen1990",
-                       "محمد أحمد عبد الفتاح"
+                       "محمد أحمد عبد الفتاح",
+                       "ديفيد"
                ]
        },
        "apihelp-main-param-action": "أي فعل للعمل.",
        "apihelp-main-param-format": "صيغة الخرج.",
+       "apihelp-main-param-assertuser": "التحقق من أن المستخدم الحالي هو المستخدم المسمى.",
+       "apihelp-main-param-requestid": "سيتم إدراج أي قيمة معينة هنا في الاستجابة. يمكن أن تُستخدَم لتمييز الطلبات.",
+       "apihelp-main-param-servedby": "تتضمن اسم المضيف الذي الخدم طلب في النتائج.",
+       "apihelp-main-param-curtimestamp": "تشمل الطابع الزمني الحالي في النتيجة.",
+       "apihelp-main-param-responselanginfo": "تشمل اللغات المستخدمة لأجل <var>uselang</var> and <var>errorlang</var> في النتيجة.",
+       "apihelp-main-param-errorsuselocal": "إذا ما أعطيت، النصوص الخطأ ستستخدم الرسائل المخصصة محليا من نطاق {{ns:MediaWiki}}.",
        "apihelp-block-description": "منع مستخدم.",
+       "apihelp-block-param-user": "اسم المستخدم، أو عنوان IP أو نطاق عنوان IP لمنعه. لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1userid</var>",
+       "apihelp-block-param-userid": "معرف المستخدم لمنعه، لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1user</var>",
        "apihelp-block-param-reason": "السبب للمنع.",
+       "apihelp-block-param-anononly": "منع المستخدمين المجهولين فقط (أي تعطيل تعديلات المجهولين من  عنوان IP هذا).",
        "apihelp-block-param-nocreate": "امنع إنشاء الحسابات.",
+       "apihelp-block-param-autoblock": "منع آخر عنوان IP مستخدم تلقائيا، وأية عناوين IP لاحقة حاولت الدخول من خلاله.",
+       "apihelp-block-param-noemail": "منع المستخدم من إرسال البريد الإلكتروني من خلال الويكي. (يتطلب صلاحية <code>blockemail</code>).",
+       "apihelp-block-param-hidename": "إخفاء اسم المستخدم من سجل المنع. (يتطلب صلاحية <code>hideuser</code>).",
+       "apihelp-block-param-allowusertalk": "تسمح للمستخدم لتحرير صفحة النقاش الخاصة (يعتمد على <var>[[mw:Manual:$wgBlockAllowsUTEdit|$wgBlockAllowsUTEdit]]</var>).",
+       "apihelp-block-param-watchuser": "مشاهدة صفحة المستخدم ونقاش IP.",
+       "apihelp-block-example-ip-simple": "منع عنوان IP <kbd>192.0.2.5</kbd> لمدة ثلاثة أيام بسبب >المخالفة الأولى</kbd>.",
+       "apihelp-block-example-user-complex": "منع المستخدم <kbd>المخرب</kbd> لأجل غير مسمى بسبب <kbd>التخريب</kbd>، ومنع إنشاء حساب جديد وإرسال بريد إلكتروني.",
+       "apihelp-changeauthenticationdata-description": "تغيير بيانات المصادقة للمستخدم الحالي.",
+       "apihelp-changeauthenticationdata-example-password": "محاولة تغيير كلمة المرور للمستخدم الحالي إلى <kbd>ExamplePassword</kbd>.",
+       "apihelp-checktoken-description": "تحقق من صحة رمز من <kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>.",
        "apihelp-checktoken-param-type": "نوع من الرموز يجري اختبارها.",
        "apihelp-checktoken-param-token": "اختبار الرموز.",
        "apihelp-checktoken-param-maxtokenage": "أقصى عمر للرمز يسمح، في ثوان.",
+       "apihelp-checktoken-example-simple": "اختبار صلاحية رمز <kbd>csrf</kbd>.",
+       "apihelp-clearhasmsg-description": "مسح <code>hasmsg</code> العلم للمستخدم الحالي.",
+       "apihelp-clearhasmsg-example-1": "مسح <code>hasmsg</code> العلم للمستخدم الحالي.",
+       "apihelp-clientlogin-description": "تسجيل الدخول إلى ويكي باستخدام التدفق التفاعلي.",
+       "apihelp-clientlogin-example-login": "بدء عملية تسجيل الدخول إلى الويكي كمستخدم <kbd>Example</kbd> بكلمة المرور <kbd>ExamplePassword</kbd>.",
+       "apihelp-clientlogin-example-login2": "واصلة تسجيل الدخول بعد استجابة <samp>UI</samp> لعاملي الصادقة، إمداد <var>OATHToken</var> ل<kbd>987654</kbd>.",
+       "apihelp-compare-description": "الحصول على الفرق بين صفحتين. يجب تمرير عنوان الصفحة أو رقم المراجعة أو معرف الصفحة لكل من \"من\" و\"إلى\".",
        "apihelp-compare-param-fromtitle": "العنوان الأول للمقارنة.",
        "apihelp-compare-param-fromid": "رقم الصفحة الأول للمقارنة.",
        "apihelp-compare-param-fromrev": "أول مراجعة للمقارنة.",
        "apihelp-compare-param-totitle": "العنوان الثاني للمقارنة.",
        "apihelp-compare-param-toid": "رقم الصفحة الثاني للمقارنة.",
        "apihelp-compare-param-torev": "المراجعة الثانية للمقارنة.",
+       "apihelp-compare-example-1": "إنشاء فرق بين المراجعة 1 و2.",
        "apihelp-createaccount-description": "انشاء حساب مستخدم جديد",
+       "apihelp-createaccount-example-create": "بدء عملية إنشاء المستخدم <kbd>Example</kbd> بكلمة المرور <kbd>ExamplePassword</kbd>.",
        "apihelp-createaccount-param-name": "اسم المستخدم.",
+       "apihelp-createaccount-param-domain": "مجال للمصادقة الخارجية (اختياري).",
+       "apihelp-createaccount-param-token": "حصلت على رمز إنشاء حساب في الطلب الأول.",
        "apihelp-createaccount-param-email": "عنوان البريد الإلكتروني للمستخدم (اختياري).",
        "apihelp-createaccount-param-realname": "الاسم الحقيقي للمستخدم (اختياري).",
        "apihelp-createaccount-param-mailpassword": "اذا تم تعيين اي قيمة, سيتم ارسال كلمة سر عشوائية للمستخدم عن طريق الاميل.",
+       "apihelp-createaccount-param-reason": "السبب اختياري لإنشاء الحساب لوضعه في السجلات.",
+       "apihelp-createaccount-param-language": "رمز اللغة لتعيينه كافتراضي للمستخدم (اختياري، لغة المحتوى الافتراضية).",
+       "apihelp-createaccount-example-pass": "إنشاء المستخدم <kbd>testuser</kbd> بكلمة المرور <kbd>test123</kbd>.",
+       "apihelp-createaccount-example-mail": "إنشاء مستخدم <kbd>testmailuser</kbd> وأرسل كلمة المرور بالبريد الإلكتروني بشكل عشوائي.",
+       "apihelp-cspreport-description": "مستخدمة من قبل المتصفحات للإبلاغ عن انتهاكات سياسة أمن المحتوى. لا ينبغي أبدا أن تستخدم هذه الوحدة، إلا عند استخدامها تلقائيا باستخدام متصفح ويب CSP متوافق.",
+       "apihelp-cspreport-param-reportonly": "علم على أنه تقرير عن سياسة الرصد، وليس فرض سياسة",
        "apihelp-delete-description": "حذف صفحة.",
+       "apihelp-delete-param-title": "عنوان الصفحة للحذف. لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1pageid</var",
+       "apihelp-delete-param-pageid": "معرف الصفحة للحذف. لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1pageid</var",
+       "apihelp-delete-param-reason": "سبب الحذف. إذا لم يُحدَّد، سوف تُستخدَم أحد الأسباب التي تنشأ تلقائيا.",
+       "apihelp-delete-param-tags": "تغيير وسوم لتطبيق الإدخال في سجل الحذف.",
        "apihelp-delete-param-watch": "أضف الصفحة إلى لائحة مراقبة المستعمل الحالي",
        "apihelp-delete-param-unwatch": "إزالة الصفحة من قائمة المراقبة للمستخدم الحالي.",
+       "apihelp-delete-param-oldimage": "اسم الصورة القديمة لحذفها كما هو منصوص عليه [[Special:ApiHelp/query+imageinfo|action=query&prop=imageinfo&iiprop=archivename]].",
+       "apihelp-delete-example-simple": "حذف <kbd>Main Page</kbd>.",
+       "apihelp-delete-example-reason": "حذف <kbd>Main Page</kbd> بسبب <kbd>Preparing for move</kbd>.",
        "apihelp-disabled-description": "هذا الاصدار تم تعطيله.",
        "apihelp-edit-description": "إنشاء وتعديل الصفحات.",
+       "apihelp-edit-param-title": "عنوان الصفحة للحذف. لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1pageid</var",
+       "apihelp-edit-param-pageid": "معرف الصفحة لتحريرها. لا يمكن أن يُستخدَم جنبا إلى جنب مع <var>$1pageid</var",
+       "apihelp-edit-param-section": "رقم القسم. <kbd>0</kbd> للقسم العلوي، <kbd>new</kbd> لقسم جديد.",
        "apihelp-edit-param-sectiontitle": "عنوان لقسم جديد.",
        "apihelp-edit-param-text": "محتوى الصفحة",
+       "apihelp-edit-param-summary": "ملخص التعديل. أيضا عنوان القسم عند عدم تعيين $1section=new and $1sectiontitle.",
+       "apihelp-edit-param-tags": "عدل الوسوم لتطبيق المراجعة.",
+       "apihelp-edit-param-minor": "تعديل طفيف",
        "apihelp-edit-param-notminor": "تعديل غير طفيف.",
-       "apihelp-edit-param-bot": "علم على هذا التعديل كبوت.",
+       "apihelp-edit-param-bot": "علم على هذا التعديل كتعديل بوت.",
+       "apihelp-edit-param-basetimestamp": "الطابع الزمني للمراجعة الأساسية، ويُستخدَم للكشف عن الحروب التحريرية، ويمكن الحصول عليها من خلال [[Special:ApiHelp/query+revisions|action=query&prop=revisions&rvprop=timestamp]].",
+       "apihelp-edit-param-starttimestamp": "الطابع الزمني عند بدء عملية التحرير، ويُستخدَم للكشف عن الحروب التحريرية، ويمكن الحصول عليها من خلال <var>[[Special:ApiHelp/main|curtimestamp]]</var> when beginning the edit process (e.g. when loading the page content to edit).",
+       "apihelp-edit-param-recreate": "تجاوز أية أخطاء حول الصفحة التي تم حذفها في هذه الأثناء.",
        "apihelp-edit-param-createonly": "لا تحرر الصفحة إذا كان موجودا بالفعل.",
+       "apihelp-edit-param-nocreate": "يحدث خطأ إذا كانت الصفحة غير موجودة.",
        "apihelp-edit-param-watch": "أضف الصفحة إلى لائحة مراقبة المستعمل الحالي",
        "apihelp-edit-param-unwatch": "إزالة الصفحة من قائمة المراقبة للمستخدم الحالي.",
+       "apihelp-edit-param-prependtext": "إضافة هذا النص إلى بداية الصفحة. تجاوز $1text.",
+       "apihelp-edit-param-appendtext": "إضافة هذا النص إلى بداية الصفحة. تجاوز $1text.\n\nاستخدم $1section=جديد لحاق القسم الجديد، بدلا من هذا الوسيط.",
+       "apihelp-edit-param-undo": "التراجع عن هذه المراجعة. تجاوز $1text, $1prependtext و$1appendtext.",
+       "apihelp-edit-param-undoafter": "التراجع عن جميع المراجعات من $1undo لهذه. إذا لم يتم التغيير، تراجع عن تعديل واحد فقط.",
+       "apihelp-edit-param-redirect": "حل التحويلات تلقائيا.",
+       "apihelp-edit-param-contentmodel": "نموذج المحتوى للمحتوى الجديد.",
+       "apihelp-edit-param-token": "ينبغي دائما أن يُرسَل الرمز كوسيط أخير، أو على الأقل بعد الوسيط $1text.",
        "apihelp-edit-example-edit": "عدل صفحة.",
+       "apihelp-edit-example-prepend": "إضافة البادئة <kbd>_&#95;NOTOC_&#95;</kbd> إلى الصفحة.",
+       "apihelp-edit-example-undo": "التراجع عن التعديلات 13579 خلال 13585 بملخص تلقائي.",
        "apihelp-emailuser-description": "مراسلة المستخدم",
+       "apihelp-emailuser-param-target": "مستخدم لإرسال بريد إلكتروني له.",
+       "apihelp-emailuser-param-subject": "رأس الموضوع",
+       "apihelp-emailuser-param-text": "جسم البريد الإلكتروني",
+       "apihelp-emailuser-param-ccme": "إرسال نسخة من هذه الرسالة لي.",
+       "apihelp-emailuser-example-email": "أرسل بريدا إلكترونيا للمستخدم <kbd>WikiSysop</kbd> بالنص  <kbd>Content</kbd>.",
+       "apihelp-expandtemplates-description": "يوسع كافة القوالب ضمن نصوص الويكي.",
        "apihelp-expandtemplates-param-title": "عنوان الصفحة.",
+       "apihelp-expandtemplates-param-text": "نص ويكي للتحويل.",
+       "apihelp-expandtemplates-param-revid": "معرف المراجعة، ل<nowiki>{{REVISIONID}}</nowiki> والمتغيرات مماثلة.",
+       "apihelp-expandtemplates-paramvalue-prop-wikitext": "نص الويكي الموسع",
+       "apihelp-expandtemplates-paramvalue-prop-properties": "خصائص الصفحة التي تحددها الكلمات السحرية الموسعة في نص الويكي.",
+       "apihelp-expandtemplates-paramvalue-prop-volatile": "إذا كان الإخراج سريع التأثر، ينبغي عدم استخدامه في أي مكان آخر داخل الصفحة.",
+       "apihelp-expandtemplates-paramvalue-prop-jsconfigvars": "يعطي متغيرات تكوين جافا سكريبت الخاصة بهذه الصفحة.",
+       "apihelp-expandtemplates-paramvalue-prop-encodedjsconfigvars": "يعطي متغيرات تكوين جافا سكريبت الخاصة بهذه الصفحة كسلسلة JSON.",
+       "apihelp-expandtemplates-paramvalue-prop-parsetree": "شجرة تحليل XML للمدخلات.",
+       "apihelp-expandtemplates-param-includecomments": "إدراج أو عدم إدراج تعليقات HTML في الإخراج.",
+       "apihelp-expandtemplates-param-generatexml": "ولد شجرة تحليل XML (حل محلها $1prop=parsetree).",
+       "apihelp-expandtemplates-example-simple": "توسيع نص الويكي <kbd><nowiki>{{Project:Sandbox}}</nowiki></kbd>.",
+       "apihelp-feedcontributions-description": "إرجاع تغذية مساهمات المستخدم.",
+       "apihelp-feedcontributions-param-feedformat": "هيئة التلقيم.",
+       "apihelp-feedcontributions-param-user": "أي المستخدمين سيتم الحصول على تبرعات لهم.",
+       "apihelp-feedcontributions-param-namespace": "أي نطاق ستتم تصفية المساهمات حسبه.",
+       "apihelp-feedcontributions-param-year": "من سنة (وأقدم).",
+       "apihelp-feedcontributions-param-month": "من شهر (وأقدم).",
+       "apihelp-feedcontributions-param-tagfilter": "تصفية المساهمات التي بها هذه الوسوم.",
+       "apihelp-feedcontributions-param-deletedonly": "اعرض المساهمات المحذوفة فقط.",
+       "apihelp-feedcontributions-param-toponly": "تظهر فقط التعديلات التي هي أحدث المراجعات.",
+       "apihelp-feedcontributions-param-newonly": "أظهر إنشاء الصفحات فقط",
+       "apihelp-feedcontributions-param-hideminor": "إخفاء التعديلات الطفيفة.",
+       "apihelp-feedcontributions-param-showsizediff": "عرض حجم الفرق بين النسخ.",
+       "apihelp-feedrecentchanges-param-feedformat": "هيئة التلقيم.",
+       "apihelp-feedrecentchanges-param-namespace": "نطاق لتقييد النتائج.",
+       "apihelp-feedrecentchanges-param-invert": "جميع النطاقات عدا المختار.",
+       "apihelp-feedrecentchanges-param-associated": "تشمل النطاق المرتبط (نقاش أو الرئيسي).",
+       "apihelp-feedrecentchanges-param-days": "أيام لتقييد النتائج.",
+       "apihelp-feedrecentchanges-param-limit": "الحد الأقصى للنتائج المُرجعة",
+       "apihelp-feedrecentchanges-param-from": "أظهر التغييرات منذ",
+       "apihelp-feedrecentchanges-param-hideminor": "إخفاء التعديلات الطفيفة.",
+       "apihelp-feedrecentchanges-param-hidebots": "إخفاء التغييرات التي أجرتها بوتات.",
+       "apihelp-feedrecentchanges-param-hideanons": "إخفاء التغييرات التي أجراها مستخدمون مجهولون.",
+       "apihelp-feedrecentchanges-param-hideliu": "إخفاء التغييرات التي أجراها مستخدمون مسجلون.",
+       "apihelp-feedrecentchanges-param-hidepatrolled": "إخفاء التغييرات المراجعة.",
+       "apihelp-feedrecentchanges-param-hidemyself": "إخفاء التغييرات التي قام بها المستخدم الحالي.",
+       "apihelp-feedrecentchanges-param-hidecategorization": "إخفاء تغيير عضوية التصنيف.",
        "apihelp-feedrecentchanges-param-tagfilter": "فلتر بالوسم.",
+       "apihelp-feedrecentchanges-param-target": "أحدث التغييرات في الصفحات الموصولة من هذه الصفحة فقط",
+       "apihelp-feedrecentchanges-param-showlinkedto": "أظهر التغييرات للصفحات الموصولة للصفحة المعطاة عوضا عن ذلك",
+       "apihelp-feedrecentchanges-param-categories": "أظهر التغييرات في الصفحات في كل تصنيف من هذه التصنيفات فقط.",
+       "apihelp-feedrecentchanges-param-categories_any": "أظهر التغييرات في الصفحات في أي تصنيف بدلا من ذلك.",
        "apihelp-feedrecentchanges-example-simple": " اظهر التغييرات الحديثة",
        "apihelp-feedrecentchanges-example-30days": "أظهر التغييرات الأخيرة في 30 يوم.",
+       "apihelp-feedwatchlist-description": "إرجاع تغذية قائمة المراقبة.",
+       "apihelp-feedwatchlist-param-feedformat": "هيئة التلقيم.",
+       "apihelp-feedwatchlist-param-hours": "صفحات قائمة معدلة ضمن عدة ساعات من الآن.",
+       "apihelp-feedwatchlist-example-default": "عرض تغذية قائمة المراقبة.",
        "apihelp-feedwatchlist-example-all6hrs": "اظهر كل التغييرات في اخر 6 ساعات",
+       "apihelp-filerevert-description": "استرجع الملف لنسخة قديمة.",
+       "apihelp-filerevert-param-filename": "اسم الملف المستهدف، دون البادئة ملف:.",
        "apihelp-filerevert-param-comment": "تعليق الرفع.",
+       "apihelp-filerevert-example-revert": "استرجاع <kbd>Wiki.png</kbd> لنسحة <kbd>2011-03-05T15:27:40Z</kbd>.",
+       "apihelp-help-description": "عرض مساعدة لوحدات محددة.",
+       "apihelp-help-param-modules": "وحدات لعرض مساعدة لها (قيم وسائط <var>action</var> و<var>format</var> أو<kbd>main</kbd>). يمكن تحديد الوحدات الفرعية ب <kbd>+</kbd>.",
+       "apihelp-help-param-submodules": "تشمل المساعدة للوحدات الفرعية من الوحدة المسماة.",
+       "apihelp-help-param-recursivesubmodules": "تشمل المساعدة للوحدات الفرعية بشكل متكرر.",
+       "apihelp-help-param-helpformat": "شكل مخرجات المساعدة.",
+       "apihelp-help-param-wrap": "التفاف المخرجات في بنية استجابة API القياسية.",
+       "apihelp-help-param-toc": "يتضمن جدول المحتويات في مخرجات HTML.",
+       "apihelp-help-example-main": "مساعدة للوحدة الرئيسية.",
+       "apihelp-help-example-submodules": "مساعدة ل<kbd>action=query</kbd> وجميع الوحدات الفرعية لها.",
        "apihelp-help-example-recursive": "كل المساعدة في صفحة واحدة.",
-       "apihelp-import-param-summary": "تعليق الاستيراد.",
+       "apihelp-help-example-help": "مساعدة لوحدة المساعدة نفسها.",
+       "apihelp-help-example-query": "مساعدة لوحدتي استعلام فرعيتين.",
+       "apihelp-imagerotate-description": "تدوير صورة واحدة أو أكثر.",
+       "apihelp-imagerotate-param-rotation": "درجة تدوير الصورة في اتجاه عقارب الساعة.",
+       "apihelp-imagerotate-example-simple": "تدوير <kbd>File:Example.png</kbd> بمقدار <kbd>90</kbd> درجة.",
+       "apihelp-imagerotate-example-generator": "تدوير جميع الصور في <kbd>Category:Flip</kbd> بمقدار <kbd>180</kbd> درجة.",
+       "apihelp-import-param-summary": "ملخص إدخال سجل الاستيراد.",
+       "apihelp-import-param-xml": "ملف XML مرفوع.",
+       "apihelp-import-param-interwikisource": "بالنسبة لواردات الإنترويكي: ويكي للاستيراد منه.",
+       "apihelp-import-param-interwikipage": "بالنسبة لواردات الإنترويكي: صفحة لاستيرادها.",
+       "apihelp-import-param-fullhistory": "بالنسبة لواردات الإنترويكي: استيراد التاريخ كاملا، وليست النسخة الحالية فقط.",
+       "apihelp-import-param-templates": "بالنسبة لواردات الإنترويكي: الإستيراد شمل كافة القوالب كذلك.",
+       "apihelp-import-param-namespace": "استيراد إلى هذا النطاق. لا يمكن أن يُستخدَم إلى جانب <var>$1rootpage</var>.",
+       "apihelp-import-param-rootpage": "استيراد كصفحة فرعية لهذه الصفحة. لا يمكن أن يُستخدَم إلى جانب <var>$1rootpage</var>.",
+       "apihelp-import-example-import": "استيراد [[meta:Help:ParserFunctions]] للنطاق 100 بالتاريخ الكامل.",
+       "apihelp-linkaccount-description": "ربط حساب من موفر طرف ثالث للمستخدم الحالي.",
+       "apihelp-linkaccount-example-link": "بدء عملية ربط حساب من <kbd>Example</kbd>.",
+       "apihelp-login-description": "سجل دخولك الآن واحصل على مصادقة الكوكيز، وينبغي استخدام هذا الإجراء فقط في تركيبة مع [[Special:BotPasswords|خاص:كلمات مرور البوت]]. تم إهمال استخدام لتسجيل الدخول للحساب الرئيسي وقد يفشل دون سابق إنذار. لتسجيل الدخول بأمان إلى الحساب الرئيسي; استخدم <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
+       "apihelp-login-description-nobotpasswords": "سجل دخولك الآن واحصل على مصادقة الكوكيز. هذا العمل مستنكر وقد يفشل دون سابق إنذار. لتسجيل الدخول بأمان إلى الحساب الرئيسي; استخدم <kbd>[[Special:ApiHelp/clientlogin|action=clientlogin]]</kbd>.",
        "apihelp-login-param-name": "اسم المستخدم.",
        "apihelp-login-param-password": "كلمة السر",
        "apihelp-login-param-domain": "النطاق (اختياري).",
+       "apihelp-login-param-token": "تم الحصول على رمز الدخول في الطلب الأول.",
+       "apihelp-login-example-gettoken": "استرداد رمز تسجيل الدخول.",
        "apihelp-login-example-login": "تسجيل الدخول",
+       "apihelp-logout-description": "تسجيل الخروج ومسح بيانات الجلسة.",
+       "apihelp-logout-example-logout": "تسجيل خروج المستخدم الحالي.",
+       "apihelp-managetags-description": "أداء المهام الإدارية المتعلقة بتغيير الوسوم.",
+       "apihelp-managetags-param-operation": "أي الإجراءات ستنفذ:\n؛ إنشاء: إنشاء وسم التغيير جديدة للاستخدام اليدوي.\n؛ حذف: إزالة وسم التغيير من قاعدة البيانات، بما في ذلك إزالة الوسم من كافة المراجعات، وإدخالات التغيير الأخيرة، وإدخالات السجل المستخدم.\n؛ تنشيط: تنشيط وسم التغيير، مما يسمح للمستخدمين بتطبيقه يدويا.\n; إلغاء: إلغاء تنشيط وسم التغيير، ومنع المستخدمين من تطبيقه يدويا.",
+       "apihelp-managetags-param-reason": "سبب اختياري لإنشاء، وحذف، وتفعيل أو تعطيل الوسم.",
+       "apihelp-managetags-param-ignorewarnings": "إذا كان سيتم تجاهل أي تحذيرات تصدر خلال العملية.",
+       "apihelp-managetags-example-create": "إنشاء وسم مسمى <kbd>spam</kbd> بسبب <kbd>For use in edit patrolling</kbd>",
+       "apihelp-managetags-example-delete": "حذف <kbd>vandlaism</kbd> وسم بسبب <kbd>Misspelt</kbd>",
+       "apihelp-managetags-example-activate": "تنشيط الوسم المسمى <kbd>spam</kbd> بسبب <kbd>For use in edit patrolling</kbd>",
+       "apihelp-managetags-example-deactivate": "تعطيل الوسم المسمى <kbd>spam</kbd> بسبب <kbd>No longer required</kbd>",
        "apihelp-mergehistory-description": "ادمج تاريخ الصفحة.",
+       "apihelp-mergehistory-param-from": "عنوان الصفحة التي سيتم دمج تاريخها. لا يمكن أن تُستخدَم بجانب <var>$1fromid</var>.",
+       "apihelp-mergehistory-param-fromid": "معرف الصفحة التي سيتم دمج تاريخها. لا يمكن أن تُستخدَم بجانب <var>$1from</var>.",
+       "apihelp-mergehistory-param-to": "عنوان الصفحة التي سيتم دمج تاريخها. لا يمكن أن تُستخدَم بجانب <var>$1toid</var>.",
+       "apihelp-mergehistory-param-toid": "معرف الصفحة التي سيتم دمج تاريخها. لا يمكن أن تُستخدَم بجانب <var>$1to</var>.",
+       "apihelp-mergehistory-param-timestamp": "الطابع الزمني للمراجعات التي سيتم نقلها من تاريخ صفحة المصدر إلى تاريخ صفحة الوجهة. إذا تم حذفها، سيتم دمج تاريخ الصفحة كاملا من صفحة المصدر إلى صفحة الوجهة.",
+       "apihelp-mergehistory-param-reason": "سبب دمج التاريخ.",
+       "apihelp-mergehistory-example-merge": "دمج تاريخ <kbd>Oldpage</kbd> كاملا إلى <kbd>Newpage</kbd>.",
+       "apihelp-mergehistory-example-merge-timestamp": "دمج مراجعات الصفحة <kbd>Oldpage</kbd> dating up to <kbd>2015-12-31T04:37:41Z</kbd> إلى <kbd>Newpage</kbd>.",
        "apihelp-move-description": "نقل صفحة.",
+       "apihelp-move-param-from": "عنوان الصفحة للنقل. لا يمكن أن تُستخدَم بجانب <var>$1pageid</var",
+       "apihelp-move-param-fromid": "معرف الصفحة للنقل. لا يمكن أن تُستخدَم بجانب <var>$1pageid</var",
+       "apihelp-move-param-to": "عنوان لإعادة تسمية الصفحة له.",
        "apihelp-move-param-reason": "السبب لإعادة التسمية.",
+       "apihelp-move-param-movetalk": "إعادة تسمية صفحة النقاش، إن وُجِدت.",
+       "apihelp-move-param-movesubpages": "إعادة تسمية الصفحات الفرعية، إن وُجِدت.",
+       "apihelp-move-param-noredirect": "لا تنشئ تحويلة.",
+       "apihelp-move-param-watch": "إضافة الصفحة والتحويلة إلى قائمة مراقبة المستخدم الحالي.",
+       "apihelp-move-param-unwatch": "إزالة الصفحة والتحويلة إلى قائمة مراقبة المستخدم الحالي.",
        "apihelp-move-param-ignorewarnings": "تجاهل أي تحذيرات.",
+       "apihelp-move-example-move": "انقل <kbd>Badtitle</kbd> إلى <kbd>Goodtitle</kbd> دون ترك تحويلة.",
+       "apihelp-opensearch-description": "بحث الويكي باستخدام بروتوكول أوبن سيرش OpenSearch.",
        "apihelp-opensearch-param-search": "سطر البحث",
        "apihelp-opensearch-param-limit": "الحد الأقصى للنتائج المُرجعة",
        "apihelp-opensearch-param-namespace": "النطاقات للبحث.",
+       "apihelp-opensearch-param-suggest": "لا تفعل شيئا إذا كان <var>[[mw:Manual:$wgEnableOpenSearchSuggest|$wgEnableOpenSearchSuggest]]</var> خاطئا.",
+       "apihelp-opensearch-param-format": "شكل الإخراج.",
+       "apihelp-opensearch-param-warningsaserror": "إذا تم رفع التحذيرات ب<kbd>format=json</kbd>, أعد أخطاء API بدلا من تجاهلها.",
+       "apihelp-opensearch-example-te": "العثور على صفحات تبدأ ب<kbd>Te</kbd>.",
+       "apihelp-options-param-reset": "إعادة تعيين التفضيلات إلى إعدادات الموقع الإفتراضية.",
+       "apihelp-options-param-resetkinds": "قائمة أنواع الخيارات لإعادة ضبطها عندما يتم تعيين خيار <var>$1reset</var>.",
+       "apihelp-options-param-optionname": "اسم الخيار الذي ينبغي ضبطه إلى القيمة التي قدمها <var>$1optionvalue</var>.",
+       "apihelp-options-param-optionvalue": "قيمة للخيار المحدد من قبل <var>$1optionname</var>.",
+       "apihelp-options-example-reset": "إعادة تعيين كل التفضيلات.",
+       "apihelp-options-example-change": "غير تفضيلات <kbd>skin</kbd> و<kbd>hideminor</kbd>.",
+       "apihelp-options-example-complex": "إعادة تعيين جميع تفضيلات، ثم تعيين <kbd>skin</kbd> و<kbd>nickname</kbd>.",
+       "apihelp-paraminfo-description": "الحصول على معلومات حول وحدات API.",
+       "apihelp-paraminfo-param-helpformat": "شكل سلاسل المساعدة.",
+       "apihelp-paraminfo-param-mainmodule": "الحصول على معلومات عن وحدة (المستوى الأعلى) الرئيسية أيضا. استخدم <kbd>$1modules=main</kbd> بدلا من ذلك.",
+       "apihelp-paraminfo-param-formatmodules": "قائمة بأسماء أشكال الوحدات (قيم الوسيط <var>format</var>). استخدم <var>$1modules</var> بدلا من ذلك.",
+       "apihelp-paraminfo-example-1": "عرض معلومات عن <kbd>[[Special:ApiHelp/parse|action=parse]]</kbd> و<kbd>[[Special:ApiHelp/jsonfm|format=jsonfm]]</kbd> و<kbd>[[Special:ApiHelp/query+allpages|action=query&list=allpages]]</kbd> و<kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd>.",
+       "apihelp-paraminfo-example-2": "أظهر المعلومات لجميع الوحدات الفرعية ل<kbd>[[Special:ApiHelp/query|action=query]]</kbd>.",
+       "apihelp-parse-param-title": "عنوان الصفحة التي ينتمي النص إليها.إذا تم حذفها، <var>$1contentmodel</var> يجب أن تكون محددة، و[[API]] سيتم استخدامه كعنوان.",
+       "apihelp-parse-param-text": "نص للتحليل. استخدم <var>$1title</var> أو <var>$1contentmodel</var> للتحكم في نموذج المحتوى.",
+       "apihelp-parse-param-summary": "ملخص للتحليل.",
+       "apihelp-parse-param-page": "تحليل محتوى هذه الصفحة. لا يمكن أن تُستخدَم بجانب <var>$1text</var> and <var>$1title</var>.",
+       "apihelp-parse-param-pageid": "حلل محتوى هذه الصفحة. تجاوز <var>$1page</var>.",
+       "apihelp-parse-param-redirects": "لو <var>$1page</var> أو <var>$1pageid</var> is تم تعيينها للتحويل، حلها.",
+       "apihelp-parse-param-oldid": "تحليل مضمون هذا التعديل. تجاوز <var>$1page</var> و<var>$1pageid</var>.",
+       "apihelp-parse-param-prop": "أي قطعة من المعلومات تريد الحصول عليها:",
+       "apihelp-parse-paramvalue-prop-langlinks": "يعطي وصلات اللغات في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-categories": "يعطي التصنيفات في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-categorieshtml": "يعطي إصدار HTML للتصنيفات.",
+       "apihelp-parse-paramvalue-prop-links": "يعطي الوصلات الداخلية في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-templates": "يعطي القوالب في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-images": "يعطي الصور في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-externallinks": "يعطي الوصلات الخارجية في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-sections": "يعطي الأقسام في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-displaytitle": "يضيف العنوان في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-headitems": "<span class=\"apihelp-deprecated\">Deprecated.</span> يعطي عناصر لوضعها في <code>&lt;head&gt;</code> الصفحة.",
+       "apihelp-parse-paramvalue-prop-headhtml": "يعطي تحليل <code>&lt;head&gt;</code> الصفحة.",
+       "apihelp-parse-paramvalue-prop-jsconfigvars": "يعطي متغيرات تكوين جافا سكريبت الخاصة بهذه الصفحة. للتطبيق; استخدم <code>mw.config.set()</code>.",
+       "apihelp-parse-paramvalue-prop-encodedjsconfigvars": "يعطي متغيرات تكوين جافا سكريبت الخاصة بهذه الصفحة كسلسلة JSON.",
+       "apihelp-parse-paramvalue-prop-indicators": "يعطي HTML مؤشرات حالة الصفحة المستخدمة في الصفحة.",
+       "apihelp-parse-paramvalue-prop-iwlinks": "يعطي وصلات اللغات في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-wikitext": "يعطي نصوص الويكي الأصلية التي تم تحليلها.",
+       "apihelp-parse-paramvalue-prop-properties": "يعطي الخصائص المختلفة المحددة في تحليل نصوص الويكي.",
+       "apihelp-parse-paramvalue-prop-limitreportdata": "يعطي تقرير الحد بطريقة منظمة. لا يعطي أية بيانات، عندما يتم تعيين <var>$1disablelimitreport</var>.",
+       "apihelp-parse-paramvalue-prop-limitreporthtml": "يعطي إصدار HTML لتقرير الحد. لا يعطي أية بيانات، عندما يتم تعيين<var>$1disablelimitreport</var>.",
+       "apihelp-parse-paramvalue-prop-parsetree": "شجرة تحليل XML لمحتويات المراجعة (يتطلب نموذج محتوى <code>$1</code>)",
+       "apihelp-parse-param-pst": "قم بتحويل قبل الحفظ على المدخلات قبل تحليل ذلك. صالح فقط عند استخدامه مع النص.",
+       "apihelp-parse-param-effectivelanglinks": "يشمل وصلات لغة المقدمة بواسطة ملحقات (للاستخدام مع <kbd>$1prop=langlinks</kbd>).",
+       "apihelp-parse-param-disablelimitreport": "تجاهل تقرير الحد (\"NewPP limit report\") من مخرجات المحلل.",
+       "apihelp-parse-param-disablepp": "استخدم <var>$1disablelimitreport</var> بدلا من ذلك.",
+       "apihelp-parse-param-disableeditsection": "تجاهل روابط تحرير الأقسام من مخرجات المحلل.",
+       "apihelp-parse-param-disabletidy": "لا تشغل تنظيف HTML (على سبيل المثال مرتبة) على مخرجات المحلل.",
+       "apihelp-parse-param-generatexml": "توليد شجرة تحليل XML (يتطلب نموذج المحتوى <code>$1</code>; حل محلها <kbd>$2prop=parsetree</kbd>).",
+       "apihelp-parse-param-preview": "تحليل في وضع المعاينة.",
+       "apihelp-parse-param-sectionpreview": "تحليل في وضع معاينة القسم (يمكن وضع المعاينة أيضا).",
+       "apihelp-parse-param-disabletoc": "تجاهل جدول المحتويات في المخرجات.",
+       "apihelp-parse-param-contentformat": "نموذج المحتوى المسلسل يُستخدَم للنص المدخل. صالح فقط عند استخدامه مع $1text.",
        "apihelp-parse-example-page": "تحليل صفحة.",
+       "apihelp-parse-example-text": "تحليل نصوص ويكي",
+       "apihelp-parse-example-texttitle": "تحليل نصوص ويكي، تحديد عنوان الصفحة.",
+       "apihelp-parse-example-summary": "تحليل الملخص.",
+       "apihelp-patrol-description": "مراجعة صفحة أو مراجعة.",
+       "apihelp-patrol-param-rcid": "معرف أحدث التغييرات للمراجعة",
+       "apihelp-patrol-param-revid": "معرف مراجعة للمراجعة",
+       "apihelp-patrol-param-tags": "تغيير وسوم لتطبيق الإدخال في سجل المراجعة.",
        "apihelp-patrol-example-rcid": "ابحث عن تغيير جديد",
        "apihelp-patrol-example-revid": "راجع مراجعة.",
        "apihelp-protect-description": "غير مستوى الحماية لصفحة.",
+       "apihelp-protect-param-title": "عنوان الصفحة ل (إزالة) الحماية. لا يمكن أن تُستخدَم بجانب $1pageid.",
+       "apihelp-protect-param-pageid": "معرف الصفحة ل (إزالة) الحماية. لا يمكن أن تُستخدَم بجانب $1pageid.",
+       "apihelp-protect-param-reason": "سبب (إزالة) الحماية.",
+       "apihelp-protect-param-tags": "تغيير وسوم لتطبيق الإدخال في سجل الحماية.",
+       "apihelp-protect-param-watch": "إذا تم الضبط، أضف الصفحة (غير) المحمية لقائمة مراقبة المستخدم الحالي.",
        "apihelp-protect-example-protect": "حماية صفحة.",
+       "apihelp-protect-example-unprotect": "إلغاء حماية الصفحة من خلال وضع قيود ل<kbd>all</kbd> (أي يُسمَح أي شخص باتخاذ الإجراءات).",
+       "apihelp-protect-example-unprotect2": "إلغاء حماية الصفحة عن طريق عدم وضع أية قيود.",
+       "apihelp-purge-param-forcelinkupdate": "تحديث جداول الروابط.",
+       "apihelp-purge-param-forcerecursivelinkupdate": "تحديث جدول الروابط، وتحديث جداول الروابط لأية صفحة تستخدم هذه الصفحة كقالب.",
+       "apihelp-purge-example-simple": "إفراغ كاش <kbd>Main Page</kbd> وصفحة <kbd>API</kbd>.",
+       "apihelp-purge-example-generator": "إفراغ كاش أول 10 صفحات في النطاق الرئيسي.",
+       "apihelp-query-description": "جلب البيانات من وعن ميدياويكي. يجب على جميع تعديلات البيانات أولا استخدام استعلام للحصول على رمز لمنع الاعتداء من المواقع الخبيثة.",
+       "apihelp-query-param-prop": "أي الخصائص تريد الحصول على صفحات استعلام عنها.",
+       "apihelp-query-param-list": "أي القوائم تريد الحصول عليها.",
+       "apihelp-query-param-meta": "أي البيانات الوصفية تريد الحصول عليها.",
+       "apihelp-query-param-export": "تصدير المراجعات الحالية لجميع الصفحات المعينة أو المولدة.",
+       "apihelp-query-param-exportnowrap": "إعادة تصدير XML دون التفاف عليه في نتيجة XML (نفس شكل [[Special:Export|خاص:تصدير]]). يمكن استخدامها فقط مع $1export.",
+       "apihelp-query-param-rawcontinue": "إرجاع <samp>query-continue</samp> بيانات خام للاستمرار.",
+       "apihelp-query-example-revisions": "جلب [[Special:ApiHelp/query+siteinfo|معلومات الموقع]] و[[Special:ApiHelp/query+revisions|مراجعات]] <kbd>Main Page</kbd>.",
+       "apihelp-query-example-allpages": "جلب مراجعات الصفحات التي تبدأ ب<kbd>API/</kbd>.",
+       "apihelp-query+allcategories-description": "تعداد جميع التصنيفات.",
+       "apihelp-query+allcategories-param-from": "التصنيف الذي يبدأ التعداد منه.",
+       "apihelp-query+allcategories-param-to": "التصنيف الذي يقف التعداد عنده.",
+       "apihelp-query+allcategories-param-prefix": "ابحث عن جميع التصنيفات التي تبدأ أسماؤها بهذه القيمة.",
+       "apihelp-query+allcategories-param-dir": "اتجاه الفرز.",
+       "apihelp-query+allcategories-param-limit": "كم عدد الفئات في الإرجاع.",
+       "apihelp-query+allcategories-param-prop": "أي الخصائص تريد الحصول عليها:",
+       "apihelp-query+allcategories-paramvalue-prop-size": "أضف عدد الصفحات في هذا التصنيف.",
+       "apihelp-query+allcategories-example-generator": "استرداد المعلومات حول صفحة التصنيف نفسها للتصنيفات التي تبدأ ب<kbd>List</kbd>.",
+       "apihelp-query+alldeletedrevisions-description": "قائمة جميع المراجعات المحذوفة بواسطة المستخدم أو في نطاق.",
+       "apihelp-query+alldeletedrevisions-paraminfo-useronly": "يمكن أن تُستخدَم فقط مع <var>$3user</var>.",
+       "apihelp-query+alldeletedrevisions-paraminfo-nonuseronly": "لا يمكن أن تُستخدَم مع <var>$3user</var>.",
+       "apihelp-query+alldeletedrevisions-param-end": "الطابع الزمني الذي يقف التعداد منه.",
+       "apihelp-query+alldeletedrevisions-param-from": "بدء الإدراج في القائمة من هذا العنوان.",
+       "apihelp-query+alldeletedrevisions-param-to": "وقف الإدراج في القائمة من هذا العنوان.",
+       "apihelp-query+alldeletedrevisions-param-prefix": "ابحث عن جميع عناوين الصفحات التي تبدأ أسماؤها بهذه القيمة.",
+       "apihelp-query+alldeletedrevisions-param-tag": "مراجعات القائمة فقط تم وسمها بهذ الوسم.",
+       "apihelp-query+alldeletedrevisions-param-user": "أدرج المراجعات التي كتبها هذا المستخدم فقط.",
+       "apihelp-query+alldeletedrevisions-param-excludeuser": "لا تدرج المراجعات التي كتبها هذا المستخدم.",
+       "apihelp-query+alldeletedrevisions-param-namespace": "أدرج الصفحات  في هذا النطاق فقط.",
+       "apihelp-query+alldeletedrevisions-param-generatetitles": "عندما يُستخدَم كمولد، ولد عناوين بدلا من معرفات المراجعات.",
+       "apihelp-query+allfileusages-description": "قائمة جميع استخدامات الملفات، بما في ذلك غير الموجودة.",
+       "apihelp-query+allfileusages-param-from": "عنوان الملف لبدء التعداد منه.",
+       "apihelp-query+allfileusages-param-to": "عنوان الملف لوقف التعداد منه.",
+       "apihelp-query+allfileusages-param-prefix": "البحث عن كل عناوين الملفات التي تبدأ بهذه القيمة.",
+       "apihelp-query+allfileusages-param-prop": "أي قطعة من المعلومات تريد تضمينها:",
+       "apihelp-query+allfileusages-paramvalue-prop-ids": "تضيف معرفات استخدام الصفحات (لا يمكن استخدامها مع $1unique).",
+       "apihelp-query+allfileusages-paramvalue-prop-title": "تضيف عنوان الملف.",
+       "apihelp-query+allfileusages-param-limit": "كم عدد مجموع البنود للعودة.",
+       "apihelp-query+allimages-description": "تعداد كافة الصور بشكل متتالي.",
+       "apihelp-query+allimages-param-sort": "خاصية للفرز وفقًا لها.",
+       "apihelp-query+allimages-param-from": "عنوان الصورة لبدء التعداد منه. يمكن استخدامها مع $1sort=name فقط.",
+       "apihelp-query+allimages-param-to": "عنوان الصورة لوقف التعداد منه. يمكن استخدامها مع $1sort=name فقط.",
+       "apihelp-query+allimages-param-start": "طابع زمني لبدء التعداد منه. يمكن استخدامه مع $1sort فقط.",
+       "apihelp-query+allimages-param-end": "طابع زمني لإنهاء التعداد منه. يمكن استخدامه مع $1sort فقط.",
+       "apihelp-query+allimages-param-prefix": "البحث عن كل عناوين الصور التي تبدأ بهذه القيمة. يمكن استخدامها مع $1sort فقط.",
+       "apihelp-query+allimages-param-sha1": "SHA1 تجزئة الصورة. تجاوز $1sha1base36.",
+       "apihelp-query+allimages-param-sha1base36": "SHA1 تجزئة الصورة في قاعدة 36 (تُستخدَم في ميدياويكي).",
+       "apihelp-query+allimages-param-filterbots": "كيفية تصفية الملفات التي تم تحميلها بواسطة بوتات. يمكن استخدامها مع $1sort=timestamp فقط. لا يمكن أن تُستخدَم بجانب $1user.",
+       "apihelp-query+allimages-param-mime": "عن أي أنواع MIME تبحث، على سبيل المثال <kbd>image/jpeg</kbd>.",
+       "apihelp-query+allimages-example-B": "أظهر قائمة الملفات التي تبدأ ب<kbd>B</kbd>.",
+       "apihelp-query+allimages-example-recent": "أظهر قائمة الملفات التي تم تحميلها مؤخرا، على غرار [[Special:NewFiles|خاص:ملفات جديدة]].",
+       "apihelp-query+allimages-example-mimetypes": "أظهر قائمة الملفات من نوع MIME <kbd>image/png</kbd> أو <kbd>image/gif</kbd>",
+       "apihelp-query+allimages-example-generator": "عرض معلومات حول 4 ملفات تبدأ بالحرف <kbd>T</kbd>.",
+       "apihelp-query+alllinks-description": "تعداد كافة الروابط التي تشير إلى نطاق معين.",
+       "apihelp-query+alllinks-param-from": "عنوان الرابط لبدء التعداد منه.",
+       "apihelp-query+alllinks-param-to": "عنوان الرابط لوقف التعداد منه.",
+       "apihelp-query+alllinks-param-prefix": "البحث عن كل العناوين المرتبطة التي تبدأ بهذه القيمة.",
+       "apihelp-query+alllinks-param-prop": "أي قطعة من المعلومات تريد تضمينها:",
+       "apihelp-query+alllinks-paramvalue-prop-ids": "تضيف معرف الصفحة للصفحة المرتبطة (لا يمكن استخدامها مع $1unique).",
+       "apihelp-query+alllinks-paramvalue-prop-title": "تضيف عنوان الرابط.",
+       "apihelp-query+alllinks-param-namespace": "نطاق للتعداد.",
+       "apihelp-query+alllinks-param-limit": "كم عدد مجموع البنود للعودة.",
+       "apihelp-query+alllinks-example-generator": "يحصل على الصفحات التي تحتوي على وصلات.",
+       "apihelp-query+allmessages-param-prop": "أي الخصائص تريد الحصول عليها:",
+       "apihelp-query+allmessages-param-filter": "إرجاع الرسائل بالأسماء التي تحتوي على هذه السلسلة فقط.",
+       "apihelp-query+allmessages-param-lang": "إرجاع الرسائل بهذه اللغة.",
+       "apihelp-query+allmessages-param-from": "إرجاع الرسائل ابتداء من هذه الرسالة.",
+       "apihelp-query+allmessages-param-to": "إرجاع الرسائل التي تنتهي بهذه الرسالة.",
+       "apihelp-query+allmessages-param-prefix": "إرجاء الرسائل بهذه البادئة.",
+       "apihelp-query+allmessages-example-ipb": "عرض رسائل تبدأ ب<kbd>ipb-</kbd>.",
+       "apihelp-query+allmessages-example-de": "عرض رسائل <kbd>august</kbd> and <kbd>mainpage</kbd> باللغة الألمانية.",
+       "apihelp-query+allpages-description": "تعداد كافة الصفحات بشكل متتالي في نطاق معين.",
+       "apihelp-query+allpages-param-to": "عنوان الصفحة لإيقاف التعداد منه.",
+       "apihelp-query+allpages-param-prefix": "البحث عن كل عناوين الصفحات التي تبدأ بهذه القيمة.",
+       "apihelp-query+allpages-param-namespace": "نطاق للتعداد.",
        "apihelp-query+allpages-param-filterredir": "أي الصفحات للعرض.",
+       "apihelp-query+allpages-param-limit": "كم عدد مجموع الصفحات للعودة.",
+       "apihelp-query+allpages-example-B": "عرض  قائمة من الصفحات التي تبدأ بالحرف <kbd>B</kbd>.",
+       "apihelp-query+allpages-example-generator": "عرض معلومات حول 4 صفحات تبدأ بالحرف <kbd>T</kbd>.",
+       "apihelp-query+allredirects-param-from": "عنوان التحويلة لبدء التعداد منه.",
+       "apihelp-query+allredirects-param-to": "عنوان التحويلة لإيقاف التعداد منه.",
+       "apihelp-query+allredirects-param-prefix": "ابحث عن جميع عناوين الصفحات المستهدفة التي تبدأ بهذه القيمة.",
+       "apihelp-query+allredirects-param-prop": "أي قطعة من المعلومات تريد تضمينها:",
+       "apihelp-query+allredirects-paramvalue-prop-ids": "تضيف معرف الصفحة لصفحة التحويل (لا يمكن استخدامها مع $1unique).",
+       "apihelp-query+allredirects-paramvalue-prop-title": "تضيف عنوان التحويلة.",
+       "apihelp-query+allredirects-param-namespace": "نطاق للتعداد.",
+       "apihelp-query+allredirects-param-limit": "كم عدد مجموع البنود للعودة.",
+       "apihelp-query+allredirects-example-generator": "يحصل على الصفحات التي تحتوي على تحويلات.",
        "apihelp-query+allrevisions-description": "اعرض كل المراجعات.",
+       "apihelp-query+allrevisions-param-start": "التصنيف الذي يبدأ التعداد منه.",
+       "apihelp-query+allrevisions-param-end": "الطابع الزمني الذي يقف التعداد منه.",
+       "apihelp-query+allrevisions-param-generatetitles": "عندما يُستخدَم كمولد، ولد عناوين بدلا من معرفات المراجعات.",
+       "apihelp-query+mystashedfiles-param-prop": "أي الخصائص تريد لجلب للملفات.",
+       "apihelp-query+mystashedfiles-paramvalue-prop-size": "جلب حجم الملف وأبعاد الصورة.",
        "apihelp-query+blocks-example-simple": "قائمة المنع.",
        "apihelp-query+imageinfo-paramvalue-prop-userid": "إضافة هوية المستخدم الذي قام بتحميل كل إصدار ملف.",
        "apihelp-query+prefixsearch-param-offset": "عدد النتائج المراد تخطيها.",
index 3818ce9..6634645 100644 (file)
@@ -18,7 +18,7 @@
        "apihelp-main-param-origin": "Пры звароце да API з дапамогай міждамэннага AJAX-запыту (CORS), выстаўце парамэтру значэньне зыходнага дамэну. Ён мусіць быць уключаны ў кожны папярэдні запыт і такім чынам мусіць быць часткай URI-запыту (ня цела POST).\n\nДля аўтэнтыфікаваных запытаў ён мусіць супадаць з адной з крыніц у загалоўку <code>Origin</code>, павінна быць зададзена нешта кшталту <kbd>https://en.wikipedia.org</kbd> або <kbd>https://meta.wikimedia.org</kbd>. Калі парамэтар не супадае з загалоўкам <code>Origin</code>, будзе вернуты адказ з кодам памылкі 403. Калі парамэтар супадае з загалоўкам <code>Origin</code> і крыніца знаходзіцца ў белым сьпісе, будуць выстаўленыя загалоўкі <code>Access-Control-Allow-Origin</code> і <code>Access-Control-Allow-Credentials</code>.\n\nДля неаўтэнтыфікаваных запытаў выстаўце значэньне <kbd>*</kbd>. Гэта прывядзе да выстаўленьня загалоўку <code>Access-Control-Allow-Origin</code>, але <code>Access-Control-Allow-Credentials</code> будзе мець значэньне <code>false</code> і ўсе зьвесткі пра карыстальніка будуць абмежаваныя.",
        "apihelp-main-param-uselang": "Мова для выкарыстаньня ў перакладах паведамленьняў. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> з <kbd>siprop=languages</kbd> вяртае сьпіс кодаў мовы, або трэба вызначыць <kbd>user</kbd>, каб ужываць налады мовы цяперашняга карыстальніка, або вызначыць <kbd>content</kbd>, каб ужываць мову зьместу гэтай вікі.",
        "apihelp-block-description": "Блякаваньне ўдзельніка.",
-       "apihelp-block-param-user": "Імя ўдзельніка, IP-адрас або IP-дыяпазон, якія вы хочаце заблякаваць.",
+       "apihelp-block-param-user": "Імя ўдзельніка, IP-адрас або IP-дыяпазон, якія вы хочаце заблякаваць. Ня можа быць ужыты разам з <var>$1userid</var>",
        "apihelp-block-param-expiry": "Час заканчэньня. Можа быць адносным (напрыклад, <kbd>5 months</kbd> або <kbd>2 weeks</kbd>) ці абсалютным (напрыклад, <kbd>2014-09-18T12:34:56Z</kbd>). Калі выстаўлены на <kbd>infinite</kbd>, <kbd>indefinite</kbd> ці <kbd>never</kbd>, блякаваньне будзе бестэрміновым.",
        "apihelp-block-param-reason": "Прычына блякаваньня.",
        "apihelp-block-param-anononly": "Заблякаваць толькі ананімных удзельнікаў (напрыклад, забараніць ананімныя праўкі з гэтага IP-адрасу).",
index fde631c..d26d1d4 100644 (file)
@@ -21,5 +21,6 @@
        "apihelp-edit-param-contentmodel": "নতুন বিষয়বস্তুর, বিষয়বস্তু-মডেল।",
        "apihelp-edit-example-edit": "একটি পাতা সম্পাদনা করুন",
        "apihelp-edit-example-prepend": "একটি পৃষ্ঠার পূর্বে <kbd>_&#95;NOTOC_&#95;</kbd> লিখুন।",
-       "apihelp-login-example-login": "প্রবেশ"
+       "apihelp-login-example-login": "প্রবেশ",
+       "apierror-nosuchuserid": "$1 আইডি যুক্ত কোন ব্যবহারকারী নেই।"
 }
index cf50f90..e8fd165 100644 (file)
@@ -26,7 +26,7 @@
        "apihelp-main-param-origin": "Pokud k API přistupujete pomocí mezidoménového AJAXového požadavku (CORS), nastavte tento parametr na doménu původu. Musí být součástí všech předběžných požadavků, takže musí být součástí URI požadavku (nikoli těla POSTu).\n\nU autentizovaných požadavků hodnota musí přesně odpovídat jednomu z původů v hlavičce <code>Origin</code>, takže musí být nastavena na něco jako <kbd>https://en.wikipedia.org</kbd> nebo <kbd>https://meta.wikimedia.org</kbd>. Pokud parametr neodpovídá hlavičce <code>Origin</code>, bude vrácena odpověď 403. Pokud parametr odpovídá hlavičce <code>Origin</code> a tento původ je na bílé listině, budou nastaveny hlavičky <code>Access-Control-Allow-Origin</code> a <code>Access-Control-Allow-Credentials</code>.\n\nU neautentizovaných požadavků uveďte hodnotu <kbd>*</kbd>. To způsobí nastavení hlavičky <code>Access-Control-Allow-Origin</code>, ale hlavička <code>Access-Control-Allow-Credentials</code> bude <code>false</code> a budou omezena všechna data specifická pro uživatele.",
        "apihelp-main-param-uselang": "Jazyk, který se má použít pro překlad hlášení. Pomocí <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> se <kbd>siprop=languages</kbd> získáte seznam jazykových kódů nebo zadejte „<kbd>user</kbd>“ pro použití předvoleného jazyka aktuálního uživatele či „<kbd>content</kbd>“ pro použití jazyka obsahu této wiki.",
        "apihelp-block-description": "Zablokovat uživatele.",
-       "apihelp-block-param-user": "Uživatelské jméno, IP adresa nebo rozsah IP adres, které chcete zablokovat.",
+       "apihelp-block-param-user": "Uživatelské jméno, IP adresa nebo rozsah IP adres, které chcete zablokovat. Nelze použít dohromady s <var>$1userid</var>.",
        "apihelp-block-param-reason": "Důvod bloku.",
        "apihelp-block-param-anononly": "Zablokovat pouze anonymní uživatele (tj. zakázat editovat anonymně z této IP).",
        "apihelp-block-param-nocreate": "Nedovolit registraci nových uživatelů.",
        "apihelp-query+watchlistraw-description": "Získat všechny stránky, které jsou aktuálním uživatelem sledovány.",
        "apihelp-query+watchlistraw-example-simple": "Seznam sledovaných stránek uživatele.",
        "apihelp-stashedit-param-summary": "Změnit shrnutí.",
-       "apihelp-unblock-param-user": "Uživatel, IP adresa nebo záběr IP adres k odblokování. Nelze použít dohromady s <var>$1id</var>.",
+       "apihelp-unblock-param-user": "Uživatel, IP adresa nebo rozsah IP adres k odblokování. Nelze použít dohromady s <var>$1id</var> nebo <var>$luserid</var>.",
        "apihelp-watch-example-watch": "Sledovat stránku <kbd>Main Page</kbd>.",
        "apihelp-watch-example-generator": "Zobrazit prvních několik stránek z hlavního jmenného prostoru.",
        "apihelp-format-example-generic": "Výsledek dotazu vrátit ve formátu $1.",
index df359ac..37f169f 100644 (file)
@@ -35,7 +35,7 @@
        "apihelp-main-param-uselang": "Zu verwendende Sprache für Nachrichtenübersetzungen. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> mit <kbd>siprop=languages</kbd> gibt eine Liste der Sprachcodes zurück. Gib <kbd>user</kbd> zum Verwenden der aktuellen Benutzerspracheinstellung oder <kbd>content</kbd> an, um die Inhaltssprache des Wikis zu verwenden.",
        "apihelp-main-param-errorsuselocal": "Falls angegeben, verwenden Fehlertexte lokalisierte Nachrichten aus dem {{ns:MediaWiki}}-Namensraum.",
        "apihelp-block-description": "Einen Benutzer sperren.",
-       "apihelp-block-param-user": "Benutzername, IP-Adresse oder IP-Bereich, der gesperrt werden soll.",
+       "apihelp-block-param-user": "Benutzername, IP-Adresse oder IP-Adressbereich, der gesperrt werden soll. Kann nicht zusammen mit <var>$1userid</var> verwendet werden.",
        "apihelp-block-param-expiry": "Sperrdauer. Kann relativ (z.&nbsp;B. <kbd>5 months</kbd> oder <kbd>2 weeks</kbd>) oder absolut (z.&nbsp;B. <kbd>2014-09-18T12:34:56Z</kbd>) sein. Wenn auf <kbd>infinite</kbd>, <kbd>indefinite</kbd> oder <kbd>never</kbd> gesetzt, ist die Sperre unbegrenzt.",
        "apihelp-block-param-reason": "Sperrbegründung.",
        "apihelp-block-param-anononly": "Nur anonyme Benutzer sperren (z.&nbsp;B. anonyme Bearbeitungen für diese IP deaktivieren).",
        "apihelp-query+imageinfo-paramvalue-prop-extmetadata": "Listet formatierte Metadaten kombiniert aus mehreren Quellen auf. Die Ergebnisse sind im HTML-Format.",
        "apihelp-query+imageinfo-paramvalue-prop-archivename": "Fügt den Dateinamen der Archivversion für die nicht-letzten Versionen hinzu.",
        "apihelp-query+imageinfo-paramvalue-prop-bitdepth": "Fügt die Bittiefe der Version hinzu.",
+       "apihelp-query+imageinfo-paramvalue-prop-badfile": "Ergänzt, ob die Datei auf der [[MediaWiki:Bad image list]] ist.",
        "apihelp-query+imageinfo-param-limit": "Wie viele Dateiversionen pro Datei zurückgegeben werden sollen.",
        "apihelp-query+imageinfo-param-start": "Zeitstempel, von dem die Liste beginnen soll.",
        "apihelp-query+imageinfo-param-end": "Zeitstempel, an dem die Liste enden soll.",
        "apihelp-query+imageinfo-param-urlheight": "Ähnlich wie $1urlwidth.",
+       "apihelp-query+imageinfo-param-badfilecontexttitle": "Falls <kbd>$2prop=badfile</kbd> festgelegt ist, ist dies der verwendete Seitentitel beim Auswerten der [[MediaWiki:Bad image list]].",
        "apihelp-query+imageinfo-param-localonly": "Suche nur nach Dateien im lokalen Repositorium.",
        "apihelp-query+imageinfo-example-simple": "Rufe Informationen über die aktuelle Version von [[:File:Albert Einstein Head.jpg]] ab.",
        "apihelp-query+imageinfo-example-dated": "Rufe Informationen über Versionen von [[:File:Test.jpg]] von 2008 und später ab.",
        "apihelp-tokens-example-edit": "Ruft einen Bearbeitungstoken ab (Standard).",
        "apihelp-tokens-example-emailmove": "Ruft einen E-Mail- und Verschiebungstoken ab.",
        "apihelp-unblock-description": "Einen Benutzer freigeben.",
-       "apihelp-unblock-param-id": "ID der Sperre zum Entsperren (über <kbd>list=blocks</kbd> erhalten). Darf nicht zusammen mit <var>$1user</var> verwendet werden.",
-       "apihelp-unblock-param-user": "Freizugebender Benutzername, IP-Adressbereich oder freizugebende IP-Adresse. Kann nicht zusammen mit <var>$1id</var> verwendet werden.",
+       "apihelp-unblock-param-id": "Kennung der Sperre zur Freigabe (abgerufen durch <kbd>list=blocks</kbd>). Kann nicht zusammen mit <var>$1user</var> oder <var>$1userid</var> verwendet werden.",
+       "apihelp-unblock-param-user": "Benutzername, IP-Adresse oder IP-Adressbereich, der freigegeben werden soll. Kann nicht zusammen mit <var>$1id</var> oder <var>$1userid</var> verwendet werden.",
        "apihelp-unblock-param-reason": "Grund für die Freigabe.",
        "apihelp-unblock-param-tags": "Auf den Benutzersperr-Logbuch-Eintrag anzuwendende Änderungsmarkierungen.",
        "apihelp-unblock-example-id": "Sperrkennung #<kbd>105</kbd> freigeben.",
        "apihelp-userrights-param-add": "Fügt den Benutzer zu diesen Gruppen hinzu.",
        "apihelp-userrights-param-remove": "Entfernt den Benutzer von diesen Gruppen.",
        "apihelp-userrights-param-reason": "Grund für die Änderung.",
+       "apihelp-validatepassword-description": "Validiert ein Passwort gegen die Passwortrichtlinien des Wikis.\n\nDie Validität wird als <samp>Good</samp> gemeldet, falls das Passwort akzeptabel ist, <samp>Change</samp>, falls das Passwort zur Anmeldung verwendet werden kann, jedoch geändert werden muss oder <samp>Invalid</samp>, falls das Passwort nicht verwendbar ist.",
+       "apihelp-validatepassword-param-password": "Zu validierendes Passwort.",
+       "apihelp-validatepassword-param-user": "Der beim Austesten der Benutzerkontenerstellung verwendete Benutzername. Der angegebene Benutzer darf nicht vorhanden sein.",
+       "apihelp-validatepassword-param-email": "Die beim Austesten der Benutzerkontenerstellung verwendete E-Mail-Adresse.",
+       "apihelp-validatepassword-param-realname": "Der beim Austesten der Benutzerkontenerstellung verwendete bürgerliche Name.",
+       "apihelp-validatepassword-example-1": "Validiert das Passwort <kbd>foobar</kbd> für den aktuellen Benutzer.",
+       "apihelp-validatepassword-example-2": "Validiert das Passwort <kbd>qwerty</kbd> zum Erstellen des Benutzers <kbd>Beispiel</kbd>.",
        "apihelp-watch-example-watch": "Die Seite <kbd>Main Page</kbd> beobachten.",
        "apihelp-watch-example-unwatch": "Die Seite <kbd>Main Page</kbd> nicht beobachten.",
        "apihelp-format-example-generic": "Das Abfrageergebnis im $1-Format ausgeben.",
        "api-help-right-apihighlimits": "Höhere Beschränkungen in API-Anfragen verwenden (langsame Anfragen: $1; schnelle Anfragen: $2). Die Beschränkungen für langsame Anfragen werden auch auf Mehrwertparameter angewandt.",
        "api-help-open-in-apisandbox": "<small>[in Spielwiese öffnen]</small>",
        "api-help-authmanagerhelper-messageformat": "Zu verwendendes Format zur Rückgabe von Nachrichten.",
+       "apierror-nosuchuserid": "Es gibt keinen Benutzer mit der Kennung $1.",
+       "apierror-stashinvalidfile": "Ungültige gespeicherte Datei.",
+       "apierror-systemblocked": "Du wurdest von MediaWiki automatisch gesperrt.",
        "api-credits-header": "Danksagungen",
        "api-credits": "API-Entwickler:\n* Roan Kattouw (Hauptentwickler von September 2007 bis 2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Yuri Astrakhan (Autor, Hauptentwickler von September 2006 bis September 2007)\n* Brad Jorsch (Hauptentwickler seit 2013)\n\nBitte sende deine Kommentare, Vorschläge und Fragen an mediawiki-api@lists.wikimedia.org\noder reiche einen Fehlerbericht auf https://phabricator.wikimedia.org/ ein."
 }
index 240e167..f6eeffe 100644 (file)
        "apihelp-query+imageinfo-paramvalue-prop-archivename": "Adds the filename of the archive version for non-latest versions.",
        "apihelp-query+imageinfo-paramvalue-prop-bitdepth": "Adds the bit depth of the version.",
        "apihelp-query+imageinfo-paramvalue-prop-uploadwarning": "Used by the Special:Upload page to get information about an existing file. Not intended for use outside MediaWiki core.",
+       "apihelp-query+imageinfo-paramvalue-prop-badfile": "Adds whether the file is on the [[MediaWiki:Bad image list]]",
        "apihelp-query+imageinfo-param-limit": "How many file revisions to return per file.",
        "apihelp-query+imageinfo-param-start": "Timestamp to start listing from.",
        "apihelp-query+imageinfo-param-end": "Timestamp to stop listing at.",
        "apihelp-query+imageinfo-param-extmetadatamultilang": "If translations for extmetadata property are available, fetch all of them.",
        "apihelp-query+imageinfo-param-extmetadatafilter": "If specified and non-empty, only these keys will be returned for $1prop=extmetadata.",
        "apihelp-query+imageinfo-param-urlparam": "A handler specific parameter string. For example, PDFs might use <kbd>page15-100px</kbd>. <var>$1urlwidth</var> must be used and be consistent with <var>$1urlparam</var>.",
+       "apihelp-query+imageinfo-param-badfilecontexttitle": "If <kbd>$2prop=badfile</kbd> is set, this is the page title used when evaluting the [[MediaWiki:Bad image list]]",
        "apihelp-query+imageinfo-param-localonly": "Look only for files in the local repository.",
        "apihelp-query+imageinfo-example-simple": "Fetch information about the current version of [[:File:Albert Einstein Head.jpg]].",
        "apihelp-query+imageinfo-example-dated": "Fetch information about versions of [[:File:Test.jpg]] from 2008 and later.",
        "apihelp-userrights-example-user": "Add user <kbd>FooBot</kbd> to group <kbd>bot</kbd>, and remove from groups <kbd>sysop</kbd> and <kbd>bureaucrat</kbd>.",
        "apihelp-userrights-example-userid": "Add the user with ID <kbd>123</kbd> to group <kbd>bot</kbd>, and remove from groups <kbd>sysop</kbd> and <kbd>bureaucrat</kbd>.",
 
+       "apihelp-validatepassword-description": "Validate a password against the wiki's password policies.\n\nValidity is reported as <samp>Good</samp> if the password is acceptable, <samp>Change</samp> if the password may be used for login but must be changed, or <samp>Invalid</samp> if the password is not usable.",
+       "apihelp-validatepassword-param-password": "Password to validate.",
+       "apihelp-validatepassword-param-user": "User name, for use when testing account creation. The named user must not exist.",
+       "apihelp-validatepassword-param-email": "Email address, for use when testing account creation.",
+       "apihelp-validatepassword-param-realname": "Real name, for use when testing account creation.",
+       "apihelp-validatepassword-example-1": "Validate the password <kbd>foobar</kbd> for the current user.",
+       "apihelp-validatepassword-example-2": "Validate the password <kbd>qwerty</kbd> for creating user <kbd>Example</kbd>.",
+
        "apihelp-watch-description": "Add or remove pages from the current user's watchlist.",
        "apihelp-watch-param-title": "The page to (un)watch. Use <var>$1titles</var> instead.",
        "apihelp-watch-param-unwatch": "If set the page will be unwatched rather than watched.",
        "apierror-specialpage-cantexecute": "You don't have permission to view the results of this special page.",
        "apierror-stashedfilenotfound": "Could not find the file in the stash: $1.",
        "apierror-stashedit-missingtext": "No stashed text found with the given hash.",
+       "apierror-stashexception": "$1",
        "apierror-stashfailed-complete": "Chunked upload is already completed, check status for details.",
        "apierror-stashfailed-nosession": "No chunked upload session with this key.",
        "apierror-stashfilestorage": "Could not store upload in the stash: $1",
+       "apierror-stashinvalidfile": "Invalid stashed file.",
        "apierror-stashnosuchfilekey": "No such filekey: $1.",
        "apierror-stashpathinvalid": "File key of improper format or otherwise invalid: $1.",
        "apierror-stashwrongowner": "Wrong owner: $1",
        "apierror-stashzerolength": "File is of zero length, and could not be stored in the stash: $1.",
+       "apierror-systemblocked": "You have been blocked automatically by MediaWiki.",
        "apierror-templateexpansion-notwikitext": "Template expansion is only supported for wikitext content. $1 uses content model $2.",
        "apierror-toofewexpiries": "$1 expiry {{PLURAL:$1|timestamp was|timestamps were}} provided where $2 {{PLURAL:$2|was|were}} needed.",
        "apierror-unknownaction": "The action specified, <kbd>$1</kbd>, is not recognized.",
index 0480a64..ac6a9ae 100644 (file)
@@ -43,7 +43,8 @@
        "apihelp-main-param-origin": "Cuando se accede a la API usando una petición AJAX de distinto dominio (CORS), se establece este valor al dominio de origen. Debe ser incluido en cualquier petición pre-vuelo, y por lo tanto debe ser parte de la URI de la petición (no del cuerpo POST).\n\nEn las peticiones con autenticación, debe coincidir exactamente con uno de los orígenes de la cabecera <code>Origin</code>, por lo que debería ser algo como <kbd>https://en.wikipedia.org</kbd> o <kbd>https://meta.wikimedia.org</kbd>. Si este parámetro no coincide con la cabecera <code>Origin</code>, se devolverá una respuesta 403. Si este parámetro coincide con la cabecera <code>Origin</code> y el origen está en la lista blanca, se creará una cabecera <code>Access-Control-Allow-Origin</code>.\n\nEn las peticiones sin autenticación, introduce el valor <kbd>*</kbd>. Esto creará una cabecera <code>Access-Control-Allow-Origin</code>, pero el valor de <code>Access-Control-Allow-Credentials</code> será <code>false</code> y todos los datos que dependan del usuario estarán restringidos.",
        "apihelp-main-param-uselang": "El idioma que se utilizará para las traducciones de mensajes. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> con <kbd>siprop=languages</kbd> devuelve una lista de códigos de idiomas. También puedes introducir <kbd>user</kbd> para usar la preferencia de idioma del usuario actual, o <kbd>content</kbd> para usar el idioma de contenido de este wiki.",
        "apihelp-block-description": "Bloquear a un usuario.",
-       "apihelp-block-param-user": "El nombre de usuario, dirección IP o intervalo de IP que quieres bloquear.",
+       "apihelp-block-param-user": "Nombre de usuario, dirección IP o intervalo de IP que quieres bloquear. No se puede utilizar junto con <var>$1userid</var>",
+       "apihelp-block-param-userid": "ID de usuario para bloquear. No se puede utilizar junto con <var>$1user</var>.",
        "apihelp-block-param-expiry": "Fecha de expiración. Puede ser relativa (por ejemplo, <kbd>5 months</kbd> o <kbd>2 weeks</kbd>) o absoluta (por ejemplo, <kbd>2014-09-18T12:34:56Z</kbd>). Si se establece en <kbd>infinite</kbd>, <kbd>indefinite</kbd>, o <kbd>never</kbd>, el bloqueo será permanente.",
        "apihelp-block-param-reason": "Razón para el bloqueo.",
        "apihelp-block-param-anononly": "Bloquear solo usuarios anónimos (es decir, desactivar ediciones anónimas de esta dirección IP).",
        "apihelp-options-description": "Cambiar preferencias del usuario actual.\n\nSolo se pueden establecer opciones que estén registradas en el núcleo o en una de las extensiones instaladas u opciones con claves predefinidas con <code>userjs-</code> (diseñadas para utilizarse con scripts de usuario).",
        "apihelp-options-param-reset": "Restablece las preferencias de la página web a sus valores predeterminados.",
        "apihelp-options-param-resetkinds": "Lista de tipos de opciones a restablecer cuando la opción <var>$1reset</var> esté establecida.",
-       "apihelp-options-param-change": "Lista de cambios con el formato name=value (por ejemplo: skin=vector). El valor no puede contener caracteres de barras verticales. Si no se da ningún valor (ni siquiera un signo de igual), por ejemplo: optionname|otheroption|..., la opción se restablecerá a sus valores predeterminados.",
+       "apihelp-options-param-change": "Lista de cambios con el formato nombre=valor (por ejemplo: skin=vector). Si no se da ningún valor (ni siquiera un signo de igual), por ejemplo: optionname|otheroption|..., la opción se restablecerá a sus valores predeterminados. Si algún valor contiene el carácter tubería (<kbd>|</kbd>), se debe utilizar el [[Special:ApiHelp/main#main/datatypes|separador alternativo de múltiples valores]] para que las operaciones se realicen correctamente.",
        "apihelp-options-param-optionname": "El nombre de la opción que debe establecerse en el valor dado por <var>$1optionvalue</var>.",
        "apihelp-options-param-optionvalue": "El valor de la opción especificada por <var>$1optionname</var>.",
        "apihelp-options-example-reset": "Restablecer todas las preferencias",
        "apihelp-options-example-change": "Cambiar las preferencias <kbd>skin</kbd> y <kbd>hideminor</kbd>.",
        "apihelp-options-example-complex": "Restablecer todas las preferencias y establecer <kbd>skin</kbd> y <kbd>nickname</kbd>.",
        "apihelp-paraminfo-description": "Obtener información acerca de los módulos de la API.",
-       "apihelp-paraminfo-param-modules": "Lista de los nombres de los módulos (valores de los parámetros <var>action</var> y <var>format</var> o <kbd>main</kbd>). Se pueden especificar los submódulos con un <kbd>+</kbd>.",
+       "apihelp-paraminfo-param-modules": "Lista de los nombres de los módulos (valores de los parámetros <var>action</var> y <var>format</var> o <kbd>main</kbd>). Se pueden especificar submódulos con un <kbd>+</kbd>, todos los submódulos con <kbd>+*</kbd> o todos los submódulos recursivamente con <kbd>+**</kbd>.",
        "apihelp-paraminfo-param-helpformat": "Formato de las cadenas de ayuda.",
        "apihelp-paraminfo-param-querymodules": "Lista de los nombres de los módulos de consulta (valor de los parámetros <var>prop</var>, <var>meta</var> or <var>list</var>). Utiliza <kbd>$1modules=query+foo</kbd> en vez de <kbd>$1querymodules=foo</kbd>.",
        "apihelp-paraminfo-param-mainmodule": "Obtener también información sobre el módulo principal (primer nivel). Utilizar <kbd>$1modules=main</kbd> en su lugar.",
        "apihelp-paraminfo-param-pagesetmodule": "Obtener también información sobre el módulo PageSet (Proporcionar títulos= y amigos).",
        "apihelp-paraminfo-param-formatmodules": "Lista de los nombres del formato de los módulos (valor del parámetro <var>format</var>). Utiliza <var>$1modules</var> en su lugar.",
        "apihelp-paraminfo-example-1": "Mostrar información para <kbd>[[Special:ApiHelp/parse|action=parse]]</kbd>, <kbd>[[Special:ApiHelp/jsonfm|format=jsonfm]]</kbd>, <kbd>[[Special:ApiHelp/query+allpages|action=query&list=allpages]]</kbd> y <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd>.",
+       "apihelp-paraminfo-example-2": "Mostrar información para todos los submódulos de <kbd>[[Special:ApiHelp/query|action=query]]</kbd>.",
        "apihelp-parse-param-title": "Título de la página a la que pertenece el texto. Si se omite se debe especificar <var>$1contentmodel</var> y se debe utilizar el [[API]] como título.",
        "apihelp-parse-param-text": "Texto a analizar. Utiliza <var>$1title</var> or <var>$1contentmodel</var> para controlar el modelo del contenido.",
        "apihelp-parse-param-summary": "Resumen a analizar.",
        "apihelp-parse-paramvalue-prop-sections": "Da las secciones del wikitexto analizado.",
        "apihelp-parse-paramvalue-prop-revid": "Añade la ID de revisión de la página analizada.",
        "apihelp-parse-paramvalue-prop-displaytitle": "Añade el título del wikitexto analizado.",
-       "apihelp-parse-paramvalue-prop-headitems": "Da elementos para colocar en el <code>&lt;encabezado&gt;</code> de la página.",
+       "apihelp-parse-paramvalue-prop-headitems": "<span class=\"apihelp-deprecated\">Obsoleto.</span> Proporciona elementos para colocar en el <code>&lt;head&gt;</code> de la página.",
        "apihelp-parse-paramvalue-prop-headhtml": "Da el <code>&lt;encabezado&gt;</code> analizado de la página.",
-       "apihelp-parse-paramvalue-prop-modules": "Da los módulos de ResourceLoader utilizados en la página. <kbd>jsconfigvars</kbd> o bien <kbd>encodedjsconfigvars</kbd> deben solicitarse en conjunto con <kbd>modules</kbd>.",
-       "apihelp-parse-paramvalue-prop-jsconfigvars": "Da la configuración JavaScript de variables específica para la página.",
+       "apihelp-parse-paramvalue-prop-modules": "Proporciona los módulos de ResourceLoader utilizados en la página. Para cargar, utiliza <code>mw.loader.using()</code>. <kbd>jsconfigvars</kbd> o bien <kbd>encodedjsconfigvars</kbd> deben solicitarse en conjunto con <kbd>modules</kbd>.",
+       "apihelp-parse-paramvalue-prop-jsconfigvars": "Proporciona las variables de configuración de JavaScript específicas de la página. Para obtenerlas, utiliza <code>mw.config.set()</code>.",
        "apihelp-parse-paramvalue-prop-encodedjsconfigvars": "Da la configuración JavaScript de variables específica para la página como cadena JSON.",
        "apihelp-parse-paramvalue-prop-indicators": "Da el HTML de los indicadores de estado utilizados en la página.",
        "apihelp-parse-paramvalue-prop-iwlinks": "Da los enlaces interwiki del texto analizado.",
        "apihelp-protect-description": "Cambiar el nivel de protección de una página.",
        "apihelp-protect-param-title": "Título de la página a (des)proteger. No se puede utilizar con $1pageid.",
        "apihelp-protect-param-pageid": "ID de la página a (des)proteger. No se puede utilizar con $1title.",
-       "apihelp-protect-param-protections": "Lista de los niveles de protección, con formato <kbd>action=level</kbd> (por ejemplo: <kbd>edit=sysop</kbd>).\n\n<strong>Nota:</strong> Cualquier acción no mencionada tendrá las restricciones eliminadas.",
+       "apihelp-protect-param-protections": "Lista de los niveles de protección, con formato <kbd>action=level</kbd> (por ejemplo: <kbd>edit=sysop</kbd>). Un nivel de <kbd>all</kbd> («todos») significa que cualquier usuaro puede realizar la acción, es decir, no hay restricción.\n\n<strong>Nota:</strong> Cualquier acción no mencionada tendrá las restricciones eliminadas.",
        "apihelp-protect-param-reason": "Motivo de la (des)protección.",
        "apihelp-protect-param-tags": "Cambiar las etiquetas para aplicar a la entrada en el registro de protección.",
        "apihelp-protect-param-cascade": "Activar la protección en cascada (o sea, proteger plantillas e imágenes transcluidas usadas en esta página). Se ignorará si ninguno de los niveles de protección dados son compatibles con la función de cascada.",
        "apihelp-protect-example-protect": "Proteger una página",
-       "apihelp-protect-example-unprotect": "Desproteger una página estableciendo la restricción a <kbd>all</kbd>.",
+       "apihelp-protect-example-unprotect": "Desproteger una página estableciendo la restricción a <kbd>all</kbd> («todos», es decir, cualquier usuario puede realizar la acción).",
        "apihelp-protect-example-unprotect2": "Desproteger una página anulando las restricciones.",
        "apihelp-purge-description": "Purgar la caché de los títulos proporcionados.\n\nSe requiere una solicitud POST si el usuario no ha iniciado sesión.",
        "apihelp-purge-param-forcelinkupdate": "Actualizar las tablas de enlaces.",
        "apihelp-query-param-indexpageids": "Incluir una sección de ID de páginas adicional en la que se muestran todas las ID de páginas.",
        "apihelp-query-param-export": "Exportar las revisiones actuales de las páginas dadas o generadas.",
        "apihelp-query-param-iwurl": "Si la URL completa si el título es un interwiki.",
+       "apihelp-query-example-allpages": "Obtener revisiones de páginas que comiencen por <kbd>API/</kbd>.",
        "apihelp-query+allcategories-description": "Enumerar todas las categorías.",
        "apihelp-query+allcategories-param-from": "La categoría para comenzar la enumeración",
        "apihelp-query+allcategories-param-to": "La categoría para detener la enumeración",
        "apihelp-query+alllinks-param-namespace": "El espacio de nombres que enumerar.",
        "apihelp-query+alllinks-param-limit": "Cuántos elementos en total se devolverán.",
        "apihelp-query+alllinks-param-dir": "La dirección en la que se listará.",
+       "apihelp-query+alllinks-example-B": "Enumera los títulos enlazados, incluyendo los títulos faltantes, con los ID de página de los que provienen, empezando por <kbd>B</kbd>.",
        "apihelp-query+alllinks-example-unique": "Lista de títulos vinculados únicamente.",
        "apihelp-query+alllinks-example-unique-generator": "Obtiene todos los títulos enlazados, marcando los que falten.",
        "apihelp-query+alllinks-example-generator": "Obtiene páginas que contienen los enlaces.",
        "apihelp-query+allrevisions-param-user": "Listar solo las revisiones de este usuario.",
        "apihelp-query+allrevisions-param-excludeuser": "No listar las revisiones de este usuario.",
        "apihelp-query+allrevisions-param-namespace": "Listar solo las páginas en este espacio de nombres.",
+       "apihelp-query+allrevisions-param-generatetitles": "Cuando se utilice como generador, genera títulos en lugar de ID de revisión.",
        "apihelp-query+allrevisions-example-user": "Listar las últimas 50 contribuciones del usuario <kbd>Example</kbd>.",
        "apihelp-query+allrevisions-example-ns-main": "Listar las primeras 50 revisiones en el espacio de nombres principal.",
        "apihelp-query+mystashedfiles-description": "Obtener una lista de archivos en la corriente de carga de usuarios.",
        "apihelp-query+alltransclusions-example-unique-generator": "Obtiene todos los títulos transcluidos, marcando los que faltan.",
        "apihelp-query+alltransclusions-example-generator": "Obtiene las páginas que contienen las transclusiones.",
        "apihelp-query+allusers-description": "Enumerar todos los usuarios registrados.",
+       "apihelp-query+allusers-param-from": "El nombre de usuario por el que empezar la enumeración.",
+       "apihelp-query+allusers-param-to": "El nombre de usuario por el que finalizar la enumeración.",
        "apihelp-query+allusers-param-prefix": "Buscar todos los usuarios que empiecen con este valor.",
        "apihelp-query+allusers-param-dir": "Dirección de ordenamiento.",
        "apihelp-query+allusers-param-group": "Incluir solo usuarios en los grupos dados.",
        "apihelp-query+blocks-paramvalue-prop-range": "Añade la gama de direcciones de IP afectó por el bloque.",
        "apihelp-query+blocks-paramvalue-prop-flags": "Etiquetas la prohibición con (autoblock, anononly, etc.).",
        "apihelp-query+blocks-example-simple": "Listar bloques.",
+       "apihelp-query+categories-description": "Enumera todas las categorías a las que pertenecen las páginas.",
        "apihelp-query+categories-param-prop": "Qué propiedades adicionales obtener para cada categoría:",
        "apihelp-query+categories-paramvalue-prop-timestamp": "Añade la marca de tiempo del momento en que se añadió la categoría.",
+       "apihelp-query+categories-paramvalue-prop-hidden": "Etiqueta las categorías que están ocultas con <code>_&#95;HIDDENCAT_&#95;</code>.",
        "apihelp-query+categories-param-show": "Qué tipo de categorías mostrar.",
        "apihelp-query+categories-param-limit": "Cuántas categorías se devolverán.",
+       "apihelp-query+categories-param-categories": "Enumerar solamente estas categorías. Útil para comprobar si una página determinada está en una categoría determinada.",
        "apihelp-query+categories-param-dir": "La dirección en que ordenar la lista.",
        "apihelp-query+categories-example-simple": "Obtener una lista de categorías a las que pertenece la página <kbd>Albert Einstein</kbd>.",
        "apihelp-query+categories-example-generator": "Obtener información acerca de todas las categorías utilizadas en la página <kbd>Albert Einstein</kbd>.",
        "apihelp-query+categoryinfo-description": "Devuelve información acerca de las categorías dadas.",
        "apihelp-query+categoryinfo-example-simple": "Obtener información acerca de <kbd>Category:Foo</kbd> y <kbd>Category:Bar</kbd>",
        "apihelp-query+categorymembers-description": "Lista todas las páginas en una categoría dada.",
+       "apihelp-query+categorymembers-param-title": "Categoría que enumerar (requerida). Debe incluir el prefijo <kbd>{{ns:category}}:</kbd>. No se puede utilizar junto con <var>$1pageid</var>.",
+       "apihelp-query+categorymembers-param-pageid": "ID de página de la categoría para enumerar. No se puede utilizar junto con <var>$1title</var>.",
        "apihelp-query+categorymembers-param-prop": "Qué piezas de información incluir:",
        "apihelp-query+categorymembers-paramvalue-prop-ids": "Añade el identificador de página.",
        "apihelp-query+categorymembers-paramvalue-prop-title": "Agrega el título y el identificador del espacio de nombres de la página.",
+       "apihelp-query+categorymembers-paramvalue-prop-sortkey": "Añade la clave de ordenación utilizada para la ordenación en la categoría (cadena hexadecimal).",
+       "apihelp-query+categorymembers-paramvalue-prop-sortkeyprefix": "Añade la clave de ordenación utilizada para la ordenación en la categoría (parte legible de la clave de ordenación).",
        "apihelp-query+categorymembers-paramvalue-prop-type": "Añade el tipo en el que se categorizó la página (<samp>page</samp>, <samp>subcat</samp> or <samp>file</samp>).",
        "apihelp-query+categorymembers-paramvalue-prop-timestamp": "Añade la marca de tiempo del momento en que se incluyó la página.",
+       "apihelp-query+categorymembers-param-namespace": "Incluir solamente páginas de estos espacios de nombres. Ten en cuenta que puede haberse utilizado <kbd>$1type=subcat</kbd> o <kbd>$1type=file</kbd> en lugar de <kbd>$1namespace=14</kbd> o <kbd>6</kbd>.",
+       "apihelp-query+categorymembers-param-type": "Qué tipo de miembros de la categoría incluir. Ignorado cuando se ha establecido <kbd>$1sort=timestamp</kbd>.",
+       "apihelp-query+categorymembers-param-limit": "Número máximo de páginas que devolver.",
        "apihelp-query+categorymembers-param-sort": "Propiedad por la que realizar la ordenación.",
        "apihelp-query+categorymembers-param-dir": "Dirección en la que desea ordenar.",
+       "apihelp-query+categorymembers-param-start": "Marca de tiempo por la que empezar la enumeración. Solo se puede utilizar junto con <kbd>$1sort=timestamp</kbd>.",
+       "apihelp-query+categorymembers-param-end": "Marca de tiempo por la que terminar la enumeración. Solo se puede utilizar junto con <kbd>$1sort=timestamp</kbd>.",
+       "apihelp-query+categorymembers-param-starthexsortkey": "Clave de ordenación por la que empezar la enumeración, tal como se ha devuelto por <kbd>$1prop=sortkey</kbd>. Solo se puede utilizar junto con <kbd>$1sort=timestamp</kbd>.",
+       "apihelp-query+categorymembers-param-endhexsortkey": "Clave de ordenación por la que terminar la enumeración, tal como se ha devuelto por <kbd>$1prop=sortkey</kbd>. Solo se puede utilizar junto con <kbd>$1sort=timestamp</kbd>.",
+       "apihelp-query+categorymembers-param-startsortkeyprefix": "Prefijo de la clave de ordenación por el que empezar la enumeración. Solo se puede utilizar junto con <kbd>$1sort=sortkey</kbd>. Reemplaza <var>$1starthexsortkey</var>.",
+       "apihelp-query+categorymembers-param-endsortkeyprefix": "Prefijo de la clave de ordenación <strong>antes</strong> del cual termina la enumeración (no <strong>en</strong> el cual; si este valor existe, no será incluido). Solo se puede utilizar junto con <kbd>$1sort=sortkey</kbd>. Reemplaza <var>$1endhexsortkey</var>.",
        "apihelp-query+categorymembers-param-startsortkey": "Utilizar $1starthexsortkey en su lugar.",
        "apihelp-query+categorymembers-param-endsortkey": "Utilizar $1endhexsortkey en su lugar.",
        "apihelp-query+categorymembers-example-simple": "Obtener las primeras 10 páginas en <kbd>Category:Physics</kbd>.",
        "apihelp-query+categorymembers-example-generator": "Obtener información sobre las primeras 10 páginas de la <kbd>Category:Physics</kbd>.",
        "apihelp-query+contributors-param-limit": "Cuántos contribuyentes se devolverán.",
        "apihelp-query+contributors-example-simple": "Mostrar los contribuyentes de la página <kbd>Main Page</kbd>.",
+       "apihelp-query+deletedrevisions-param-start": "Marca de tiempo por la que empezar la enumeración. Se ignora cuando se esté procesando una lista de ID de revisión.",
+       "apihelp-query+deletedrevisions-param-end": "Marca de tiempo por la que terminar la enumeración. Se ignora cuando se esté procesando una lista de ID de revisión.",
        "apihelp-query+deletedrevisions-param-tag": "Listar solo las revisiones con esta etiqueta.",
        "apihelp-query+deletedrevisions-param-user": "Listar solo las revisiones de este usuario.",
        "apihelp-query+deletedrevisions-param-excludeuser": "No listar las revisiones de este usuario.",
        "apihelp-query+deletedrevs-paraminfo-modes": "{{PLURAL:$1|Modo|Modos}}: $2",
+       "apihelp-query+deletedrevs-param-start": "Marca de tiempo por la que empezar la enumeración.",
+       "apihelp-query+deletedrevs-param-end": "Marca de tiempo por la que terminar la enumeración.",
        "apihelp-query+deletedrevs-param-from": "Empezar a listar en este título.",
        "apihelp-query+deletedrevs-param-to": "Terminar de listar en este título.",
        "apihelp-query+deletedrevs-param-prefix": "Buscar todas las páginas que empiecen con este valor.",
        "apihelp-query+deletedrevs-param-limit": "La cantidad máxima de revisiones que listar.",
        "apihelp-query+deletedrevs-example-mode3-talk": "Listar las primeras 50 páginas en el espacio de nombres {{ns:talk}} (modo 3).",
        "apihelp-query+disabled-description": "Se ha desactivado el módulo de consulta.",
+       "apihelp-query+duplicatefiles-param-limit": "Número de archivos duplicados para devolver.",
        "apihelp-query+duplicatefiles-param-dir": "La dirección en que ordenar la lista.",
        "apihelp-query+duplicatefiles-param-localonly": "Buscar solo archivos en el repositorio local.",
        "apihelp-query+duplicatefiles-example-simple": "Buscar duplicados de [[:File:Alber Einstein Head.jpg]].",
        "apihelp-query+duplicatefiles-example-generated": "Buscar duplicados en todos los archivos.",
        "apihelp-query+embeddedin-description": "Encuentra todas las páginas que transcluyen el título dado.",
        "apihelp-query+embeddedin-param-title": "Título a buscar. No puede usarse en conjunto con $1pageid.",
+       "apihelp-query+embeddedin-param-namespace": "El espacio de nombres que enumerar.",
        "apihelp-query+embeddedin-param-dir": "La dirección en que ordenar la lista.",
        "apihelp-query+embeddedin-param-filterredir": "Cómo filtrar las redirecciones.",
        "apihelp-query+embeddedin-param-limit": "Cuántas páginas se devolverán.",
        "apihelp-query+extlinks-param-limit": "Cuántos enlaces se devolverán.",
+       "apihelp-query+extlinks-param-expandurl": "Expandir las URL relativas a un protocolo con el protocolo canónico.",
        "apihelp-query+extlinks-example-simple": "Obtener una lista de los enlaces externos en <kbd>Main Page</kbd>.",
        "apihelp-query+exturlusage-description": "Enumera páginas que contienen una URL dada.",
        "apihelp-query+exturlusage-param-prop": "Qué piezas de información incluir:",
        "apihelp-query+exturlusage-paramvalue-prop-title": "Agrega el título y el identificador del espacio de nombres de la página.",
        "apihelp-query+exturlusage-paramvalue-prop-url": "Añade el URL utilizado en la página.",
        "apihelp-query+exturlusage-param-protocol": "Protocolo del URL. Si está vacío y se establece <var>$1query</var>, el protocolo es <kbd>http</kbd>. Deja vacío esto y <var>$1query</var> para listar todos los enlaces externos.",
+       "apihelp-query+exturlusage-param-namespace": "Los espacios de nombres que enumerar.",
        "apihelp-query+exturlusage-param-limit": "Cuántas páginas se devolverán.",
+       "apihelp-query+exturlusage-param-expandurl": "Expandir las URL relativas a un protocolo con el protocolo canónico.",
        "apihelp-query+exturlusage-example-simple": "Mostrar páginas que enlacen con <kbd>http://www.mediawiki.org</kbd>.",
+       "apihelp-query+filearchive-description": "Enumerar todos los archivos borrados de forma secuencial.",
        "apihelp-query+filearchive-param-from": "El título de imagen para comenzar la enumeración",
        "apihelp-query+filearchive-param-to": "El título de imagen para detener la enumeración.",
        "apihelp-query+filearchive-param-prefix": "Buscar todos los títulos de las imágenes que comiencen con este valor.",
+       "apihelp-query+filearchive-param-limit": "Número de imágenes que devolver en total.",
        "apihelp-query+filearchive-param-dir": "La dirección en que ordenar la lista.",
+       "apihelp-query+filearchive-param-sha1": "Hash SHA1 de la imagen. Reemplaza $1sha1base36.",
+       "apihelp-query+filearchive-param-sha1base36": "Hash SHA1 de la imagen en base 36 (utilizado en MediaWiki).",
        "apihelp-query+filearchive-param-prop": "Qué información de imagen se obtendrá:",
+       "apihelp-query+filearchive-paramvalue-prop-sha1": "Añade el hash SHA-1 para la imagen.",
        "apihelp-query+filearchive-paramvalue-prop-timestamp": "Añade la marca de tiempo de la versión subida.",
        "apihelp-query+filearchive-paramvalue-prop-user": "Agrega el usuario que subió la versión de la imagen.",
        "apihelp-query+filearchive-paramvalue-prop-size": "Agrega el tamaño de la imagen en bytes y la altura, la anchura y el número de páginas (si es aplicable).",
        "apihelp-query+filearchive-paramvalue-prop-parseddescription": "Analizar la descripción de la versión.",
        "apihelp-query+filearchive-paramvalue-prop-mime": "Añade el MIME de la imagen.",
        "apihelp-query+filearchive-paramvalue-prop-mediatype": "Añade el tipo multimedia de la imagen.",
+       "apihelp-query+filearchive-paramvalue-prop-bitdepth": "Añade la profundidad de bit de la versión.",
        "apihelp-query+filearchive-paramvalue-prop-archivename": "Añade el nombre de archivo de la versión archivada para las versiones que no son las últimas.",
        "apihelp-query+filearchive-example-simple": "Mostrar una lista de todos los archivos eliminados.",
        "apihelp-query+filerepoinfo-example-simple": "Obtener información acerca de los repositorios de archivos.",
+       "apihelp-query+fileusage-description": "Encontrar todas las páginas que utilizan los archivos dados.",
        "apihelp-query+fileusage-param-prop": "Qué propiedades se obtendrán:",
        "apihelp-query+fileusage-paramvalue-prop-pageid": "Identificador de cada página.",
        "apihelp-query+fileusage-paramvalue-prop-title": "Título de cada página.",
+       "apihelp-query+fileusage-param-namespace": "Incluir solo páginas de estos espacios de nombres.",
        "apihelp-query+fileusage-param-limit": "Cuántos se devolverán.",
        "apihelp-query+fileusage-example-simple": "Obtener una lista de páginas que utilicen [[:File:Example.jpg]].",
        "apihelp-query+fileusage-example-generator": "Obtener información acerca de las páginas que utilicen [[:File:Example.jpg]].",
        "apihelp-query+imageinfo-description": "Devuelve información del archivo y su historial de subida.",
        "apihelp-query+imageinfo-param-prop": "Qué información del archivo se obtendrá:",
+       "apihelp-query+imageinfo-paramvalue-prop-timestamp": "Añade la marca de tiempo a la versión actualizada.",
        "apihelp-query+imageinfo-paramvalue-prop-user": "Añade el usuario que subió cada versión del archivo.",
        "apihelp-query+imageinfo-paramvalue-prop-userid": "Añade la ID de usuario que subió cada versión del archivo.",
+       "apihelp-query+imageinfo-paramvalue-prop-comment": "Comentarios sobre la versión.",
+       "apihelp-query+imageinfo-paramvalue-prop-parsedcomment": "Analizar el comentario de la versión.",
        "apihelp-query+imageinfo-paramvalue-prop-canonicaltitle": "Agrega el título canónico del archivo.",
+       "apihelp-query+imageinfo-paramvalue-prop-dimensions": "Alias para el tamaño.",
+       "apihelp-query+imageinfo-paramvalue-prop-sha1": "Añade el hash SHA-1 para la imagen.",
+       "apihelp-query+imageinfo-paramvalue-prop-mime": "Añade el tipo MIME del archivo.",
+       "apihelp-query+imageinfo-paramvalue-prop-thumbmime": "Añade el tipo MIME de la miniatura de la imagen (se requiere la URL y el parámetro $1urlwidth).",
+       "apihelp-query+imageinfo-paramvalue-prop-mediatype": "Añade el tipo multimedia de la imagen.",
+       "apihelp-query+imageinfo-paramvalue-prop-bitdepth": "Añade la profundidad de bits de la versión.",
        "apihelp-query+imageinfo-param-limit": "Cuántos revisiones de archivos se devolverán por perfil.",
+       "apihelp-query+imageinfo-param-start": "Marca de tiempo por la que empezar la enumeración.",
+       "apihelp-query+imageinfo-param-end": "Marca de tiempo por la que terminar la enumeración.",
        "apihelp-query+imageinfo-param-urlheight": "Similar a $1urlwidth.",
        "apihelp-query+imageinfo-param-extmetadatafilter": "Si se especifica y no vacío, sólo estas claves serán devueltos por $1prop=extmetadata.",
        "apihelp-query+imageinfo-param-urlparam": "Un controlador específico de la cadena de parámetro. Por ejemplo, los archivos Pdf pueden utilizar <kbd>page15-100px</kbd>. <var>$1urlwidth</var> debe ser utilizado y debe ser consistente con <var>$1urlparam</var>.",
        "apihelp-query+info-param-token": "Usa [[Special:ApiHelp/query+tokens|action=query&meta=tokens]] en su lugar.",
        "apihelp-query+info-example-simple": "Obtener información acerca de la página <kbd>Main Page</kbd>.",
        "apihelp-query+info-example-protection": "Obtén información general y protección acerca de la página <kbd>Main Page</kbd>.",
+       "apihelp-query+iwbacklinks-param-prefix": "Prefijo para el interwiki.",
        "apihelp-query+iwbacklinks-param-limit": "Cuántas páginas se devolverán.",
        "apihelp-query+iwbacklinks-param-prop": "Qué propiedades se obtendrán:",
+       "apihelp-query+iwbacklinks-paramvalue-prop-iwprefix": "Añade el prefijo del interwiki.",
        "apihelp-query+iwbacklinks-paramvalue-prop-iwtitle": "Añade el título del interwiki.",
        "apihelp-query+iwbacklinks-param-dir": "La dirección en que ordenar la lista.",
        "apihelp-query+iwbacklinks-example-simple": "Obtener las páginas enlazadas a [[wikibooks:Test]]",
        "apihelp-query+langlinks-paramvalue-prop-autonym": "Añade el nombre nativo del idioma.",
        "apihelp-query+langlinks-param-lang": "Devolver solo enlaces de idioma con este código de idioma.",
        "apihelp-query+langlinks-param-dir": "La dirección en que ordenar la lista.",
+       "apihelp-query+links-description": "Devuelve todos los enlaces de las páginas dadas.",
+       "apihelp-query+links-param-namespace": "Mostrar solo los enlaces en estos espacios de nombres.",
        "apihelp-query+links-param-limit": "Cuántos enlaces se devolverán.",
        "apihelp-query+links-param-dir": "La dirección en que ordenar la lista.",
        "apihelp-query+linkshere-param-prop": "Qué propiedades se obtendrán:",
        "apihelp-query+linkshere-paramvalue-prop-pageid": "Identificador de cada página.",
        "apihelp-query+linkshere-paramvalue-prop-title": "Título de cada página.",
        "apihelp-query+linkshere-paramvalue-prop-redirect": "Indicar si la página es una redirección.",
+       "apihelp-query+linkshere-param-namespace": "Incluir solo páginas de estos espacios de nombres.",
        "apihelp-query+linkshere-param-limit": "Cuántos se devolverán.",
        "apihelp-query+linkshere-example-simple": "Obtener una lista de páginas que enlacen a la [[Main Page]].",
        "apihelp-query+linkshere-example-generator": "Obtener información acerca de las páginas enlazadas a la [[Main Page|Portada]].",
+       "apihelp-query+logevents-description": "Obtener eventos de los registros.",
        "apihelp-query+logevents-param-prop": "Qué propiedades se obtendrán:",
        "apihelp-query+logevents-paramvalue-prop-ids": "Agrega el identificador del evento de registro.",
        "apihelp-query+logevents-paramvalue-prop-type": "Añade el tipo del evento de registro.",
        "apihelp-query+logevents-paramvalue-prop-parsedcomment": "Añade el comentario analizado del evento de registro.",
+       "apihelp-query+logevents-param-start": "Marca de tiempo por la que empezar la enumeración.",
+       "apihelp-query+logevents-param-end": "Marca de tiempo por la que terminar la enumeración.",
        "apihelp-query+pageprops-description": "Obtener diferentes propiedades de página definidas en el contenido de la página.",
        "apihelp-query+pageprops-param-prop": "Sólo listar estas propiedades de página (<kbd>[[Special:ApiHelp/query+pagepropnames|action=query&list=pagepropnames]]</kbd> devuelve los nombres de las propiedades de página en uso). Útil para comprobar si las páginas usan una determinada propiedad de página.",
        "apihelp-query+pageswithprop-param-propname": "Propiedad de página para la cual enumerar páginas (<kbd>[[Special:ApiHelp/query+pagepropnames|action=query&list=pagepropnames]]</kbd> devuelve los nombres de las propiedades de página en uso).",
        "apihelp-query+pageswithprop-paramvalue-prop-title": "Agrega el título y el identificador del espacio de nombres de la página.",
        "apihelp-query+pageswithprop-paramvalue-prop-value": "Añade el valor de la propiedad de página.",
        "apihelp-query+pageswithprop-param-limit": "El máximo número de páginas que se devolverán.",
+       "apihelp-query+pageswithprop-param-dir": "Dirección en la que se desea ordenar.",
        "apihelp-query+pageswithprop-example-simple": "Listar las 10 primeras páginas que utilicen <code>&#123;&#123;DISPLAYTITLE:&#125;&#125;</code>.",
        "apihelp-query+pageswithprop-example-generator": "Obtener información adicional acerca de las 10 primeras páginas que utilicen <code>_&#95;NOTOC_&#95;</code>.",
        "apihelp-query+prefixsearch-param-search": "Buscar cadena.",
        "apihelp-query+protectedtitles-param-level": "Listar solo títulos con estos niveles de protección.",
        "apihelp-query+protectedtitles-param-limit": "Cuántas páginas se devolverán.",
        "apihelp-query+protectedtitles-param-prop": "Qué propiedades se obtendrán:",
+       "apihelp-query+protectedtitles-paramvalue-prop-timestamp": "Añade la marca de tiempo de cuando se añadió la protección.",
        "apihelp-query+protectedtitles-paramvalue-prop-user": "Agrega el usuario que agregó la protección.",
        "apihelp-query+protectedtitles-paramvalue-prop-userid": "Agrega el identificador de usuario que agregó la protección.",
+       "apihelp-query+protectedtitles-paramvalue-prop-comment": "Añade el comentario de la protección.",
+       "apihelp-query+protectedtitles-paramvalue-prop-parsedcomment": "Añade el comentario analizado para la protección.",
        "apihelp-query+protectedtitles-paramvalue-prop-expiry": "Añade la fecha y hora de cuando se levantará la protección.",
        "apihelp-query+protectedtitles-paramvalue-prop-level": "Agrega el nivel de protección.",
        "apihelp-query+protectedtitles-example-simple": "Listar títulos protegidos.",
        "apihelp-query+querypage-param-page": "El nombre de la página especial. Recuerda, es sensible a mayúsculas y minúsculas.",
        "apihelp-query+querypage-param-limit": "Número de resultados que se devolverán.",
        "apihelp-query+querypage-example-ancientpages": "Devolver resultados de [[Special:Ancientpages]].",
+       "apihelp-query+random-param-filterredir": "Cómo filtrar las redirecciones.",
        "apihelp-query+recentchanges-description": "Enumerar cambios recientes.",
        "apihelp-query+recentchanges-param-start": "El sello de tiempo para comenzar la enumeración.",
        "apihelp-query+recentchanges-param-end": "El sello de tiempo para finalizar la enumeración.",
        "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-example-simple": "Lista de cambios recientes.",
+       "apihelp-query+redirects-description": "Devuelve todas las redirecciones a las páginas dadas.",
        "apihelp-query+redirects-param-prop": "Qué propiedades se obtendrán:",
        "apihelp-query+redirects-paramvalue-prop-pageid": "Identificador de página de cada redirección.",
        "apihelp-query+redirects-paramvalue-prop-title": "Título de cada redirección.",
        "apihelp-query+revisions+base-paramvalue-prop-comment": "Comentario del usuario para la revisión.",
        "apihelp-query+revisions+base-paramvalue-prop-content": "Texto de la revisión.",
        "apihelp-query+revisions+base-paramvalue-prop-tags": "Etiquetas para la revisión.",
+       "apihelp-query+revisions+base-param-limit": "Limitar la cantidad de revisiones que se devolverán.",
        "apihelp-query+search-param-info": "Qué metadatos devolver.",
        "apihelp-query+search-param-prop": "Qué propiedades se devolverán:",
+       "apihelp-query+search-paramvalue-prop-size": "Añade el tamaño de la página en bytes.",
+       "apihelp-query+search-paramvalue-prop-wordcount": "Añade el número de palabras de la página.",
+       "apihelp-query+search-paramvalue-prop-timestamp": "Añade la marca de tiempo de la última edición de la página.",
+       "apihelp-query+search-paramvalue-prop-snippet": "Añade un fragmento analizado de la página.",
+       "apihelp-query+search-paramvalue-prop-titlesnippet": "Añade un fragmento analizado del título de la página.",
+       "apihelp-query+search-paramvalue-prop-redirectsnippet": "Añade un fragmento analizado del título de la redirección.",
        "apihelp-query+search-paramvalue-prop-redirecttitle": "Añade el título de la redirección coincidente.",
+       "apihelp-query+search-paramvalue-prop-sectionsnippet": "Añade un fragmento analizado del título de la sección correspondiente.",
+       "apihelp-query+search-paramvalue-prop-sectiontitle": "Añade el título de la sección correspondiente.",
+       "apihelp-query+search-paramvalue-prop-categorysnippet": "Añade un fragmento analizado de la categoría correspondiente.",
+       "apihelp-query+search-paramvalue-prop-isfilematch": "Añade un booleano que indica si la búsqueda corresponde al contenido del archivo.",
        "apihelp-query+search-paramvalue-prop-score": "<span class=\"apihelp-deprecated\">Desaconsejado e ignorado.</span>",
        "apihelp-query+search-paramvalue-prop-hasrelated": "<span class=\"apihelp-deprecated\">Desaconsejado e ignorado.</span>",
        "apihelp-query+search-param-limit": "Cuántas páginas en total se devolverán.",
        "apihelp-query+search-param-interwiki": "Incluir resultados interwiki en la búsqueda, si es posible.",
+       "apihelp-query+search-param-backend": "Qué servidor de búsqueda utilizar, si no es el servidor por defecto.",
+       "apihelp-query+search-param-enablerewrites": "Habilita la reescritura de consultas internas. Algunos servidores de búsqueda pueden reescribir la consulta a una que considere que da mejores resultados, por ejemplo, corrigiendo las faltas ortográficas.",
        "apihelp-query+search-example-simple": "Buscar <kbd>meaning</kbd>.",
        "apihelp-query+search-example-text": "Buscar <kbd>meaning</kbd> en los textos.",
        "apihelp-query+search-example-generator": "Obtener información acerca de las páginas devueltas por una búsqueda de <kbd>meaning</kbd>.",
        "apihelp-query+stashimageinfo-example-params": "Devuelve las miniaturas de dos archivos escondidos.",
        "apihelp-query+tags-param-limit": "El número máximo de etiquetas para enumerar.",
        "apihelp-query+tags-param-prop": "Qué propiedades se obtendrán:",
+       "apihelp-query+tags-paramvalue-prop-name": "Añade el nombre de la etiqueta.",
        "apihelp-query+tags-paramvalue-prop-displayname": "Agrega el mensaje de sistema para la etiqueta.",
+       "apihelp-query+tags-paramvalue-prop-description": "Añade la descripción de la etiqueta.",
+       "apihelp-query+tags-paramvalue-prop-defined": "Indicar si la etiqueta está definida.",
        "apihelp-query+tags-paramvalue-prop-source": "Obtiene las fuentes de la etiqueta, que pueden incluir <samp>extension</samp> para etiquetas definidas por extensiones y <samp>manual</samp> para etiquetas que pueden aplicarse manualmente por los usuarios.",
        "apihelp-query+tags-paramvalue-prop-active": "Si la etiqueta aún se sigue aplicando.",
+       "apihelp-query+tags-example-simple": "Enumera las etiquetas disponibles.",
        "apihelp-query+templates-description": "Devuelve todas las páginas transcluidas en las páginas dadas.",
+       "apihelp-query+templates-param-namespace": "Mostrar plantillas solamente en estos espacios de nombres.",
        "apihelp-query+templates-param-limit": "Cuántas plantillas se devolverán.",
        "apihelp-query+templates-param-dir": "La dirección en que ordenar la lista.",
        "apihelp-query+transcludedin-description": "Encuentra todas las páginas que transcluyan las páginas dadas.",
        "apihelp-query+transcludedin-param-namespace": "Incluir solo las páginas en estos espacios de nombres.",
        "apihelp-query+transcludedin-param-limit": "Cuántos se devolverán.",
        "apihelp-query+transcludedin-example-simple": "Obtener una lista de páginas transcluyendo <kbd>Main Page</kbd>.",
+       "apihelp-query+usercontribs-description": "Obtener todas las ediciones realizadas por un usuario.",
        "apihelp-query+usercontribs-param-limit": "Número máximo de contribuciones que se devolverán.",
        "apihelp-query+usercontribs-param-prop": "Incluir piezas adicionales de información:",
        "apihelp-query+usercontribs-paramvalue-prop-ids": "Añade el identificador de página y el de revisión.",
        "apihelp-query+usercontribs-paramvalue-prop-title": "Agrega el título y el identificador del espacio de nombres de la página.",
        "apihelp-query+usercontribs-paramvalue-prop-timestamp": "Añade fecha y hora de la edición.",
        "apihelp-query+usercontribs-paramvalue-prop-comment": "Añade el comentario de la edición.",
+       "apihelp-query+usercontribs-paramvalue-prop-parsedcomment": "Añade el comentario analizado de la edición.",
+       "apihelp-query+usercontribs-paramvalue-prop-size": "Añade el nuevo tamaño de la edición.",
+       "apihelp-query+usercontribs-paramvalue-prop-sizediff": "Añade la diferencia de tamaño de la edición respecto de su progenitora.",
        "apihelp-query+usercontribs-paramvalue-prop-patrolled": "Etiqueta ediciones verificadas.",
        "apihelp-query+usercontribs-paramvalue-prop-tags": "Lista las etiquetas para la edición.",
        "apihelp-query+usercontribs-param-show": "Mostrar solo los elementos que coinciden con estos criterios. Por ejemplo, solo ediciones no menores: <kbd>$2show=!minor</kbd>.\n\nSi se establece <kbd>$2show=patrolled</kbd> o <kbd>$2show=!patrolled</kbd>, las revisiones más antiguas que <var>[[mw:Manual:$wgRCMaxAge|$wgRCMaxAge]]</var> ($1 {{PLURAL:$1|segundo|segundos}}) no se mostrarán.",
        "apihelp-query+users-param-prop": "Qué piezas de información incluir:",
        "apihelp-query+users-paramvalue-prop-blockinfo": "Etiqueta si el usuario está bloqueado, por quién y por qué razón.",
        "apihelp-query+users-paramvalue-prop-groups": "Lista todos los grupos a los que pertenece cada usuario.",
+       "apihelp-query+users-paramvalue-prop-implicitgroups": "Enumera todos los grupos a los que pertenece automáticamente un usuario.",
+       "apihelp-query+users-paramvalue-prop-rights": "Enumera todos los permisos que tiene cada usuario.",
        "apihelp-query+users-paramvalue-prop-editcount": "Añade el número de ediciones del usuario.",
+       "apihelp-query+users-paramvalue-prop-registration": "Añade la marca de tiempo del registro del usuario.",
        "apihelp-query+users-paramvalue-prop-gender": "Etiqueta el género del usuario. Devuelve \"masculino\", \"femenino\" o \"desconocido\".",
        "apihelp-query+users-example-simple": "Devolver información del usuario <kbd>Example</kbd>.",
        "apihelp-query+watchlist-param-start": "El sello de tiempo para comenzar la enumeración",
        "apihelp-query+watchlist-param-end": "El sello de tiempo para finalizar la enumeración.",
+       "apihelp-query+watchlist-param-namespace": "Filtrar cambios solamente a los espacios de nombres dados.",
        "apihelp-query+watchlist-param-excludeuser": "No listar cambios de este usuario.",
        "apihelp-query+watchlist-param-prop": "Qué propiedades adicionales se obtendrán:",
        "apihelp-query+watchlist-paramvalue-prop-ids": "Añade identificadores de revisiones y de páginas.",
        "apihelp-query+watchlist-paramvalue-prop-user": "Añade el usuario que hizo la edición.",
        "apihelp-query+watchlist-paramvalue-prop-userid": "Añade el identificador de usuario de quien hizo la edición.",
        "apihelp-query+watchlist-paramvalue-prop-comment": "Añade el comentario de la edición.",
+       "apihelp-query+watchlist-paramvalue-prop-parsedcomment": "Añade el comentario analizado de la edición.",
        "apihelp-query+watchlist-paramvalue-prop-timestamp": "Añade fecha y hora de la edición.",
        "apihelp-query+watchlist-paramvalue-prop-patrol": "Etiqueta las ediciones que están verificadas.",
        "apihelp-query+watchlist-paramvalue-prop-sizes": "Añade la longitud vieja y la nueva de la página.",
        "apihelp-query+watchlist-paramvalue-type-external": "Cambios externos.",
        "apihelp-query+watchlist-paramvalue-type-new": "Creaciones de páginas.",
        "apihelp-query+watchlist-paramvalue-type-log": "Entradas del registro.",
+       "apihelp-query+watchlistraw-param-limit": "Número de resultados que devolver en cada petición.",
        "apihelp-query+watchlistraw-param-prop": "Qué propiedades adicionales se obtendrán:",
        "apihelp-query+watchlistraw-param-show": "Sólo listar los elementos que cumplen estos criterios.",
        "apihelp-query+watchlistraw-param-dir": "La dirección en la que se listará.",
        "apihelp-query+watchlistraw-param-fromtitle": "Título (con el prefijo de espacio de nombres) desde el que se empezará a enumerar.",
        "apihelp-query+watchlistraw-param-totitle": "Título (con el prefijo de espacio de nombres) desde el que se dejará de enumerar.",
        "apihelp-query+watchlistraw-example-simple": "Listar las páginas de la lista de seguimiento del usuario actual.",
+       "apihelp-resetpassword-description": "Enviar un email de reinicialización de la contraseña a un usuario.",
        "apihelp-revisiondelete-description": "Eliminar y restaurar revisiones",
        "apihelp-revisiondelete-param-hide": "Qué ocultar en cada revisión.",
        "apihelp-revisiondelete-param-show": "Qué mostrar en cada revisión.",
        "apihelp-revisiondelete-param-reason": "Motivo de la eliminación o restauración.",
        "apihelp-rollback-param-summary": "Resumen de edición personalizado. Si se deja vacío se utilizará el predeterminado.",
+       "apihelp-rsd-description": "Exportar un esquema RSD (Really Simple Discovery; Descubrimiento Muy Simple).",
+       "apihelp-rsd-example-simple": "Exportar el esquema RSD.",
        "apihelp-stashedit-param-title": "Título de la página que se está editando.",
        "apihelp-stashedit-param-section": "Número de la sección. <kbd>0</kbd> para una sección superior, <kbd>new</kbd> para una sección nueva.",
        "apihelp-stashedit-param-sectiontitle": "El título de una sección nueva.",
        "apihelp-tag-example-rev": "Añadir la etiqueta <kbd>vandalism</kbd> al identificador de revisión 123 sin especificar un motivo",
        "apihelp-tag-example-log": "Eliminar la etiqueta <kbd>spam</kbd> de la entrada del registro con identificador 123 con el motivo <kbd>Wrongly applied</kbd>",
        "apihelp-unblock-description": "Desbloquear un usuario.",
-       "apihelp-unblock-param-user": "Nombre de usuario, dirección IP o intervalo de direcciones IP para desbloquear. No se puede utilizar junto con <var>$1id</var>.",
+       "apihelp-unblock-param-user": "Nombre de usuario, dirección IP o intervalo de direcciones IP para desbloquear. No se puede utilizar junto con <var>$1id</var> o <var>$luserid</var>.",
+       "apihelp-unblock-param-userid": "ID de usuario que desbloquear. No se puede utilizar junto con <var>$1id</var> o <var>$1user</var>.",
        "apihelp-unblock-param-reason": "Motivo del desbloqueo.",
        "apihelp-unblock-example-id": "Desbloquear el bloqueo de ID #<kbd>105</kbd>",
        "apihelp-unblock-example-user": "Desbloquear al usuario <kbd>Bob</kbd> con el motivo <kbd>Sorry Bob</kbd>",
+       "apihelp-undelete-param-title": "Título de la página que restaurar.",
        "apihelp-undelete-param-reason": "Motivo de la restauración.",
        "apihelp-undelete-example-revisions": "Restaurar dos revisiones de la página <kbd>Main Page</kbd>.",
+       "apihelp-upload-param-filename": "Nombre del archivo de destino.",
        "apihelp-upload-param-tags": "Cambiar etiquetas para aplicar a la entrada del registro de subidas y a la revisión de página de archivo.",
        "apihelp-upload-param-watch": "Vigilar la página.",
        "apihelp-upload-param-ignorewarnings": "Ignorar las advertencias.",
+       "apihelp-upload-param-file": "Contenido del archivo.",
+       "apihelp-upload-param-url": "URL de la que obtener el archivo.",
+       "apihelp-upload-param-filesize": "Tamaño de archivo total de la carga.",
+       "apihelp-upload-param-offset": "Posición del fragmento en bytes.",
+       "apihelp-upload-param-chunk": "Contenido del fragmento.",
+       "apihelp-upload-param-async": "Realizar de forma asíncrona las operaciones de archivo potencialmente grandes cuando sea posible.",
        "apihelp-upload-example-url": "Subir desde una URL.",
        "apihelp-userrights-param-user": "Nombre de usuario.",
        "apihelp-userrights-param-userid": "ID de usuario.",
        "apihelp-rawfm-description": "Extraer los datos de salida, incluidos los elementos de depuración, en formato JSON (embellecido en HTML).",
        "apihelp-xml-param-xslt": "Si se especifica, añade la página nombrada como una hoja de estilo XSL. El valor debe ser un título en el espacio de nombres {{ns:MediaWiki}} que termine en <code>.xsl</code>.",
        "apihelp-xml-param-includexmlnamespace": "Si se especifica, añade un espacio de nombres XML.",
+       "api-format-title": "Resultado de la API de MediaWiki",
+       "api-format-prettyprint-status": "Esta respuesta se devolvería con el estado HTTP $1 $2.",
+       "api-help-title": "Ayuda de la API de MediaWiki",
+       "api-help-lead": "Esta es una página de documentación autogenerada de la API de MediaWiki.\n\nDocumentación y ejemplos: https://www.mediawiki.org/wiki/API",
        "api-help-main-header": "Módulo principal",
        "api-help-flag-deprecated": "Este módulo está en desuso.",
+       "api-help-flag-internal": "<strong>Este módulo es interno o inestable.</strong> Su funcionamiento puede cambiar sin previo aviso.",
        "api-help-flag-readrights": "Este módulo requiere permisos de lectura.",
        "api-help-flag-writerights": "Este módulo requiere permisos de escritura.",
        "api-help-flag-mustbeposted": "Este módulo solo acepta solicitudes POST.",
        "api-help-param-integer-min": "{{PLURAL:$1|1=El valor no debe ser menor|2=Los valores no deben ser menores}} a $2.",
        "api-help-param-integer-max": "{{PLURAL:$1|1=El valor no debe ser mayor|2=Los valores no deben ser mayores}} a $3.",
        "api-help-param-integer-minmax": "{{PLURAL:$1|1=El valor debe|2=Los valores deben}} estar entre $2 y $3.",
-       "api-help-param-multi-separate": "Separar los valores con <kbd>|</kbd>.",
+       "api-help-param-multi-separate": "Separar los valores con <kbd>|</kbd> o con una [[Special:ApiHelp/main#main/datatypes|alternativa]].",
        "api-help-param-multi-max": "El número máximo de los valores es {{PLURAL:$1|$1}} ({{PLURAL:$2|$2}} para los bots).",
+       "api-help-param-multi-all": "Para especificar todos los valores, utiliza <kbd>$1</kbd>.",
        "api-help-param-default": "Predeterminado: $1",
        "api-help-param-default-empty": "Predeterminado: <span class=\"apihelp-empty\">(vacío)</span>",
        "api-help-param-continue": "Cuando haya más resultados disponibles, utiliza esto para continuar.",
        "api-help-examples": "{{PLURAL:$1|Ejemplo|Ejemplos}}:",
        "api-help-permissions": "{{PLURAL:$1|Permiso|Permisos}}:",
        "api-help-permissions-granted-to": "{{PLURAL:$1|Concedido a|Concedidos a}}: $2",
+       "api-help-authmanagerhelper-messageformat": "Formato utilizado para los mensajes devueltos.",
+       "api-help-authmanagerhelper-preservestate": "Preservar el estado de un intento fallido anterior de inicio de sesión, si es posible.",
+       "apierror-assertbotfailed": "La aserción de que el usuario tiene el derecho <code>bot</code> falló.",
+       "apierror-assertnameduserfailed": "La aserción de que el usuario es «$1» falló.",
+       "apierror-assertuserfailed": "La aserción de que el usuario está conectado falló.",
+       "apierror-autoblocked": "Tu dirección IP ha sido bloqueada automáticamente porque fue utilizada por un usuario bloqueado.",
+       "apierror-badconfig-resulttoosmall": "El valor de <code>$wgAPIMaxResultSize</code> en este wiki es demasiado pequeño como para contener información básica de resultados.",
+       "apierror-badgenerator-notgenerator": "El módulo <kbd>$1</kbd> no puede utilizarse como un generador.",
+       "apierror-badgenerator-unknown": "<kbd>generator=$1</kbd> desconocido.",
        "apierror-badip": "El parámetro IP no es válido.",
+       "apierror-badmd5": "El hash MD5 suministrado es incorrecto.",
+       "apierror-badmodule-badsubmodule": "El módulo <kbd>$1</kbd> no tiene un submódulo \"$2\".",
+       "apierror-badmodule-nosubmodules": "El módulo <kbd>$1</kbd> no tiene submódulos.",
+       "apierror-badparameter": "Valor no válido para el parámetro <var>$1</var>.",
+       "apierror-badquery": "La consulta no es válida.",
+       "apierror-badtimestamp": "Valor no válido \"$2\" para el parámetro de marca de tiempo <var>$1</var>.",
+       "apierror-badurl": "Valor no válido \"$2\" para el parámetro de URL <var>$1</var>.",
+       "apierror-baduser": "Valor no válido \"$2\" para el parámetro de usuario <var>$1</var>.",
+       "apierror-blockedfrommail": "Se te ha bloqueado de enviar email.",
+       "apierror-blocked": "Se te ha bloqueado de editar.",
+       "apierror-cantblock-email": "No tienes permiso para bloquear a los usuarios el envío de correo electrónico a través de la wiki.",
+       "apierror-cantblock": "No tienes permiso para bloquear usuarios.",
+       "apierror-cantchangecontentmodel": "No tienes permiso para cambiar el modelo de contenido de una página.",
+       "apierror-canthide": "No tienes permiso para ocultar nombres de usuario del registro de bloqueos.",
+       "apierror-cantimport-upload": "No tienes permiso para importar páginas subidas.",
+       "apierror-cantimport": "No tienes permiso para importar páginas.",
+       "apierror-import-unknownerror": "Error desconocido en la importación: $1.",
+       "apierror-invalidexpiry": "Tiempo de expiración \"$1\" no válido.",
+       "apierror-invalidparammix-cannotusewith": "El parámetro <kbd>$1</kbd> no se puede utilizar junto con <kbd>$2</kbd>.",
+       "apierror-invalidparammix-mustusewith": "El parámetro <kbd>$1</kbd> solo se puede utilizar junto con <kbd>$2</kbd>.",
+       "apierror-invalidparammix-parse-new-section": "<kbd>section=new</kbd> no se puede combinar con los parámetros <var>oldid</var>, <var>pageid</var> y <var>page</var>. Por favor, utiliza <var>title</var> y <var>text</var>.",
+       "apierror-invalidparammix": "{{PLURAL:$2|Los parámetros}} $1 no se pueden utilizar juntos.",
+       "apierror-invalidsection": "El parámetro de sección debe ser un ID de sección válido, o bien <kbd>new</kbd>.",
+       "apierror-invalidsha1base36hash": "El hash SHA1Base36 proporcionado no es válido.",
+       "apierror-invalidsha1hash": "El hash SHA1 proporcionado no es válido.",
        "apierror-invalidtitle": "Título incorrecto \"$1\".",
+       "apierror-missingparam-at-least-one-of": "{{PLURAL:$2|El parámetro|Al menos uno de los parámetros}} $1 es necesario.",
+       "apierror-missingparam-one-of": "{{PLURAL:$2|El parámetro|Uno de los parámetros}} $1 es necesario.",
+       "apierror-missingparam": "Se debe establecer el parámetro <var>$1</var>.",
+       "apierror-missingrev-pageid": "No hay ninguna revisión actual de la página con ID $1.",
+       "apierror-missingtitle": "El título especificado no existe.",
+       "apierror-missingtitle-byname": "La página $1 no existe.",
+       "apierror-moduledisabled": "El módulo <kbd>$1</kbd> ha sido deshabilitado.",
+       "apierror-multival-only-one-of": "Solo {{PLURAL:$3|se permite el valor|se permiten los valores}} $2 para el parámetro <var>$1</var>.",
+       "apierror-multival-only-one": "Solo se permite un valor para el parámetro <var>$1</var>.",
+       "apierror-multpages": "<var>$1</var> no se puede utilizar más que con una sola página.",
+       "apierror-noedit-anon": "Los usuarios anónimos no pueden editar páginas.",
+       "apierror-noedit": "No tienes permiso para editar páginas.",
+       "apierror-paramempty": "El parámetro <var>$1</var> no puede estar vacío.",
+       "apierror-permissiondenied": "No tienes permiso para $1.",
+       "apierror-permissiondenied-generic": "Permiso denegado.",
+       "apierror-permissiondenied-unblock": "No tienes permiso para desbloquear usuarios.",
+       "apierror-readapidenied": "Necesitas permiso de lectura para utilizar este módulo.",
+       "apierror-readonly": "El wiki está actualmente en modo de solo lectura.",
        "apierror-revwrongpage": "r$1 no es una revisión de $2.",
+       "apierror-specialpage-cantexecute": "No tienes permiso para ver los resultados de esta página especial.",
        "apierror-unknownerror-nocode": "Error desconocido.",
+       "apierror-unknownerror": "Error desconocido: «$1»",
+       "apierror-unknownformat": "Formato no reconocido «$1».",
+       "apierror-unrecognizedparams": "{{PLURAL:$2|Parámetro no reconocido|Parámetros no reconocidos}}: $1.",
+       "apierror-unrecognizedvalue": "Valor no reconocido para el parámetro <var>$1</var>: $2.",
+       "apiwarn-deprecation-httpsexpected": "Se ha utilizado HTTP cuando se esperaba HTTPS.",
        "apiwarn-invalidcategory": "\"$1\" no es una categoría.",
+       "apiwarn-invalidtitle": "«$1» no es un título válido.",
+       "apiwarn-invalidxmlstylesheetns": "La hoja de estilos debería estar en el espacio de nombres {{ns:MediaWiki}}.",
        "apiwarn-notfile": "\"$1\" no es un archivo.",
+       "apiwarn-validationfailed-keytoolong": "clave demasiado larga (no puede tener más de $1 bytes).",
+       "apiwarn-validationfailed": "Error de validación de <kbd>$1</kbd>: $2",
        "api-feed-error-title": "Error ($1)",
+       "api-usage-docref": "Véase $1 para el uso de la API.",
        "api-exception-trace": "$1 en $2($3)\n$4",
        "api-credits-header": "Créditos",
        "api-credits": "Desarrolladores de la API:\n* Roan Kattouw (desarrollador principal, sep. 2007-2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Yuri Astrakhan (creador y desarrollador principal, sep. 2006-sep. 2007)\n* Brad Jorsch (desarrollador principal, 2013-actualidad)\n\nEnvía comentarios, sugerencias y preguntas a mediawiki-api@lists.wikimedia.org\no informa de un error en https://phabricator.wikimedia.org/."
index 83958f0..901ff29 100644 (file)
@@ -48,7 +48,8 @@
        "apihelp-main-param-errorlang": "Langue à utiliser pour les avertissements et les erreurs. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> avec <kbd>siprop=languages</kbd> renvoyant une liste de codes de langue, ou spécifier <kbd>content</kbd> pour utiliser la langue du contenu de ce wiki, ou spécifier <kbd>uselang</kbd> pour utiliser la même valeur que le paramètre <var>uselang</var>.",
        "apihelp-main-param-errorsuselocal": "S’il est fourni, les textes d’erreur utiliseront des messages adaptés à la langue dans l’espace de noms {{ns:MediaWiki}}.",
        "apihelp-block-description": "Bloquer un utilisateur.",
-       "apihelp-block-param-user": "Nom d’utilisateur, adresse IP ou plage d’adresses IP que vous voulez bloquer.",
+       "apihelp-block-param-user": "Nom d’utilisateur, adresse IP ou plage d’adresses IP que vous voulez bloquer. Ne peut pas être utilisé en même temps que <var>$1userid</var>",
+       "apihelp-block-param-userid": "ID d'utilisateur à bloquer. Ne peut pas être utilisé avec <var>$1user</var>.",
        "apihelp-block-param-expiry": "Durée d’expiration. Peut être relative (par ex. <kbd>5 months</kbd> ou <kbd>2 weeks</kbd>) ou absolue (par ex. <kbd>2014-09-18T12:34:56Z</kbd>). Si elle est mise à <kbd>infinite</kbd>, <kbd>indefinite</kbd> ou <kbd>never</kbd>, le blocage n’expirera jamais.",
        "apihelp-block-param-reason": "Motif du blocage.",
        "apihelp-block-param-anononly": "Bloquer uniquement les utilisateurs anonymes (c’est-à-dire désactiver les modifications anonymes pour cette adresse IP).",
        "apihelp-query+imageinfo-paramvalue-prop-archivename": "Ajoute le nom de fichier de la version d’archive pour les versions autres que la dernière.",
        "apihelp-query+imageinfo-paramvalue-prop-bitdepth": "Ajoute la profondeur de bits de la version.",
        "apihelp-query+imageinfo-paramvalue-prop-uploadwarning": "Utilisé par la page Special:Upload pour obtenir de l’information sur un fichier existant. Non prévu pour être utilisé en dehors du cœur de MédiaWiki.",
+       "apihelp-query+imageinfo-paramvalue-prop-badfile": "Ajoute l'indication que le fichier est sur [[MediaWiki:Bad image list]]",
        "apihelp-query+imageinfo-param-limit": "Combien de révision de fichier renvoyer par fichier.",
        "apihelp-query+imageinfo-param-start": "Horodatage auquel démarrer la liste.",
        "apihelp-query+imageinfo-param-end": "Horodatage auquel arrêter la liste.",
        "apihelp-query+imageinfo-param-extmetadatamultilang": "Si des traductions pour la propriété extmetadata sont disponibles, les analyser toutes.",
        "apihelp-query+imageinfo-param-extmetadatafilter": "Si spécifié et non vide, seules ces clés seront renvoyées pour $1prop=extmetadata.",
        "apihelp-query+imageinfo-param-urlparam": "Une chaîne de paramètre spécifique à l’analyseur. Par exemple, les PDFs peuvent utiliser <kbd>page15-100px</kbd>. <var>$1urlwidth</var> doit être utilisé et être cohérent avec <var>$1urlparam</var>.",
+       "apihelp-query+imageinfo-param-badfilecontexttitle": "Si <kbd>$2prop=badfile</kbd> est positionné, il s'agit du titre de la page utilisé pour évaluer la [[MediaWiki:Bad image list]]",
        "apihelp-query+imageinfo-param-localonly": "Rechercher les fichiers uniquement dans le référentiel local.",
        "apihelp-query+imageinfo-example-simple": "Analyser les informations sur la version actuelle de [[:File:Albert Einstein Head.jpg]]",
        "apihelp-query+imageinfo-example-dated": "Analyser les informations sur les versions de [[:File:Test.jpg]] depuis 2008",
        "apihelp-tokens-example-edit": "Récupérer un jeton de modification (par défaut).",
        "apihelp-tokens-example-emailmove": "Récupérer un jeton de courriel et un jeton de déplacement.",
        "apihelp-unblock-description": "Débloquer un utilisateur.",
-       "apihelp-unblock-param-id": "ID du blocage à lever (obtenu via <kbd>list=blocks</kbd>). Impossible à utiliser avec <var>$1user</var>.",
-       "apihelp-unblock-param-user": "Nom d’utilisateur, adresse IP ou plage d’adresses IP à débloquer. Impossible à utiliser en même temps que <var>$1id</var>.",
+       "apihelp-unblock-param-id": "ID du blocage à lever (obtenu via <kbd>list=blocks</kbd>). Impossible à utiliser avec <var>$1user</var> ou <var>$luserid</var>.",
+       "apihelp-unblock-param-user": "Nom d’utilisateur, adresse IP ou plage d’adresses IP à débloquer. Impossible à utiliser en même temps que <var>$1id</var> ou <var>$luserid</var>.",
+       "apihelp-unblock-param-userid": "ID de l'utilisateur à débloquer. Ne peut être utilisé avec <var>$1id</var> ou <var>$1user</var>.",
        "apihelp-unblock-param-reason": "Motif de déblocage.",
        "apihelp-unblock-param-tags": "Modifier les balises à appliquer à l’entrée dans le journal de blocage.",
        "apihelp-unblock-example-id": "Lever le blocage d’ID #<kbd>105</kbd>.",
        "apihelp-userrights-param-reason": "Motif pour la modification.",
        "apihelp-userrights-example-user": "Ajouter l’utilisateur <kbd>FooBot</kbd> au groupe <kbd>bot</kbd>, et le supprimer des groupes <kbd>sysop</kbd> et <kbd>bureaucrat</kbd>.",
        "apihelp-userrights-example-userid": "Ajouter l’utilisateur d’ID <kbd>123</kbd> au groupe <kbd>robot</kbd>, et le supprimer des groupes <kbd>sysop</kbd> et <kbd>bureaucrate</kbd>.",
+       "apihelp-validatepassword-description": "Valider un mot de passe en suivant les règles des mots de passe du wiki.\n\nLa validation est <samp>Good</samp> si le mot de passe est acceptable, <samp>Change</samp> s'il peut être utilisé pour se connecter et doit être changé, ou  <samp>Invalid</samp> s'il n'est pas utilisable.",
+       "apihelp-validatepassword-param-password": "Mot de passe à valider.",
+       "apihelp-validatepassword-param-user": "Nom de l'utilisateur, pour tester la création de compte. L'utilisateur ne doit pas déja exister.",
+       "apihelp-validatepassword-param-email": "Adresse courriel, pour tester la création de compte.",
+       "apihelp-validatepassword-param-realname": "Vrai nom, pour tester la création de compte.",
+       "apihelp-validatepassword-example-1": "Valider le mot de passe <kbd>foobar</kbd> pour l'utilisateur actuel.",
+       "apihelp-validatepassword-example-2": "Valider le mot de passe <kbd>qwerty</kbd> pour la création de l'utilisateur <kbd>Example</kbd>.",
        "apihelp-watch-description": "Ajouter ou supprimer des pages de la liste de suivi de l’utilisateur actuel.",
        "apihelp-watch-param-title": "La page à (ne plus) suivre. Utiliser plutôt <var>$1titles</var>.",
        "apihelp-watch-param-unwatch": "Si défini, la page ne sera plus suivie plutôt que suivie.",
        "apierror-nosuchrevid": "Il n’y a pas de révision d’ID $1.",
        "apierror-nosuchsection": "Il n’y a pas de section $1.",
        "apierror-nosuchsection-what": "Il ’y a pas de section $1 dans $2.",
+       "apierror-nosuchuserid": "Il n'y a pas d'utilisateur ayant l'ID $1.",
        "apierror-notarget": "Vous n’avez pas spécifié une cible valide pour cette action.",
        "apierror-notpatrollable": "La révision r$1 ne peut pas être patrouillée car elle est trop ancienne.",
        "apierror-nouploadmodule": "Aucun module de téléchargement défini.",
        "apierror-stashfailed-complete": "Un téléchargement par morceaux est déjà achevé, vérifiez l’état pour plus de détails.",
        "apierror-stashfailed-nosession": "Aucune session de téléchargement par morceaux avec cette clé.",
        "apierror-stashfilestorage": "Impossible de mettre le téléchargement en réserve: $1",
+       "apierror-stashinvalidfile": "Fichier de réserve invalide.",
        "apierror-stashnosuchfilekey": "Filekey inconnue: $1.",
        "apierror-stashpathinvalid": "La clé du fichier n'a pas le bon format ou est invalide: $1 .",
        "apierror-stashwrongowner": "Erreur de propriétaire: $1",
        "apierror-stashzerolength": "Fichier est de longueur nulle, et n'a pas pu être mis dans la réserve: $1.",
+       "apierror-systemblocked": "Vous avez été bloqué automatiquement par MediaWiki.",
        "apierror-templateexpansion-notwikitext": "Le développement du modèle n'est effectif que sur un contenu wikitext. $1 utilise le modèle de contenu $2.",
        "apierror-toofewexpiries": "$1 {{PLURAL:$1|horodatage d’expiration a été fourni|horodatages d’expiration ont été fournis}} alors que $2 {{PLURAL:$2|était attendu|étaient attendus}}.",
        "apierror-unknownaction": "L'action spécifiée, <kbd>$1</kbd>, n'est pas reconnue.",
        "apiwarn-deprecation-deletedrevs": "<kbd>list=deletedrevs</kbd> est devenu obsolète. Veuillez utiliser <kbd>prop=deletedrevisions</kbd> ou <kbd>list=alldeletedrevisions</kbd> à la place.",
        "apiwarn-deprecation-expandtemplates-prop": "Comme aucune valeur n’a été spécifiée pour le paramètre <var>prop</var>, un format d’héritage a été utilisé pour la sortie. Ce format est obsolète et, dans le futur, une valeur par défaut sera fixée pour le paramètre <var>prop</var>, provoquant ainsi l’utilisation systématique du nouveau format.",
        "apiwarn-deprecation-httpsexpected": "HTTP est utilisé alors que HTTPS est attendu.",
+       "apiwarn-deprecation-login-botpw": "La connexion au compte principal via <kbd>action=login</kbd> est obsolète et peut ne plus fonctionner sans avertissement. Pour continuer à vous connecter avec <kbd>action=login</kbd>, voyez [[Special:BotPasswords]]. Pour continuer à utiliser la connexion au compte principal en toute sécurité, voyez <kbd>action=clientlogin</kbd>.",
+       "apiwarn-deprecation-login-nobotpw": "La connexion au compte principal via <kbd>action=login</kbd> est obsolète et peut ne plus fonctionner sans avertissement. Pour vous connecter en toute sécurité, voyez <kbd>action=clientlogin</kbd>.",
+       "apiwarn-deprecation-login-token": "La récupération d’un jeton via <kbd>action=login</kbd> est obsolète. Utilisez <kbd>action=query&meta=tokens&type=login</kbd> à la place.",
        "apiwarn-deprecation-parameter": "Le paramètre <var>$1</var> est obsolète.",
+       "apiwarn-deprecation-parse-headitems": "<kbd>prop=headitems</kbd> est obsolète depuis MédiaWiki 1.28. Utilisez <kbd>prop=headhtml</kbd> lors de la création de nouveaux documents HTML, ou <kbd>prop=modules|jsconfigvars</kbd> lors de la mise à jour d’un document côté client.",
        "apiwarn-deprecation-purge-get": "L'utilisation de <kbd>action=purge</kbd> via un GET est obsolète. Utiliser POST à la place.",
        "apiwarn-deprecation-withreplacement": "<kbd>$1</kbd> est obsolète. Veuillez utiliser <kbd>$2</kbd> à la place.",
+       "apiwarn-difftohidden": "Impossible de faire un diff avec r$1 : le contenu est masqué.",
        "apiwarn-errorprinterfailed": "Erreur échec imprimante. Nouvel essai sans paramètres.",
+       "apiwarn-errorprinterfailed-ex": "Erreur d’échec de l’impression (réessayera sans paramètres) : $1",
        "apiwarn-invalidcategory": "« $1 » n'est pas une catégorie.",
        "apiwarn-invalidtitle": "« $1 » n’est pas un titre valide.",
+       "apiwarn-invalidxmlstylesheetext": "Une feuille de style doit avoir une extension <code>.xsl</code>.",
+       "apiwarn-invalidxmlstylesheet": "Feuille de style spécifiée non valide ou inexistante.",
+       "apiwarn-invalidxmlstylesheetns": "La feuille de style devrait être dans l’espace de noms {{ns:MediaWiki}}.",
+       "apiwarn-moduleswithoutvars": "La propriété <kbd>modules</kbd> a été définie mais pas <kbd>jsconfigvars</kbd> ni <kbd>encodedjsconfigvars</kbd>. Les variables de configuration sont nécessaires pour une utilisation correcte du module.",
        "apiwarn-notfile": "« $1 » n'est pas un fichier.",
+       "apiwarn-nothumb-noimagehandler": "Impossible de créer la vignette car $1 n’a pas de gestionnaire d’image associé.",
+       "apiwarn-parse-nocontentmodel": "Ni <var>title</var> ni <var>contentmodel</var> n’ont été fournis, $1 est supposé.",
+       "apiwarn-parse-titlewithouttext": "<var>title</var> utilisé sans <var>text</var>, et les propriétés de page analysées sont nécessaires. Voulez-vous dire que vous voulez utiliser <var>page</var> à la place de <var>title</var> ?",
+       "apiwarn-redirectsandrevids": "La résolution de la redirection ne peut pas être utilisée avec le paramètre <var>revids</var>. Toutes les redirections vers lesquelles pointent <var>revids</var> n’ont pas été résolues.",
        "apiwarn-tokennotallowed": "L'action « $1 » n'est pas autorisée pour l'utilisateur actuel.",
+       "apiwarn-tokens-origin": "Les jetons ne peuvent pas être obtenus quand la politique de même origine n’est pas appliquée.",
        "apiwarn-toomanyvalues": "Trop de valeurs fournies pour le paramètre <var>$1</var>: la limite est $2.",
+       "apiwarn-truncatedresult": "Ce résultat a été tronqué parce que sinon, il dépasserait la limite de $1 octets.",
+       "apiwarn-unclearnowtimestamp": "Passer « $2 » comme paramètre d’horodatage <var>$1</var> a été rendu obsolète. Si, pour une raison quelconque, vous avez besoin de spécifier explicitement l’heure courante sans la recalculer du côté client, utilisez <kbd>now<kbd>.",
+       "apiwarn-unrecognizedvalues": "{{PLURAL:$3|Valeur non reconnue|Valeurs non reconnues}} pour le paramètre <var>$1</var> : $2.",
        "apiwarn-unsupportedarray": "Le paramètre <var>$1</var> utilise une syntaxe PHP de tableau non prise en charge.",
+       "apiwarn-urlparamwidth": "Valeur de la largeur définie dans <var>$1urlparam</var> ($2) ignorée en faveur de la largeur calculée à partir de <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
        "apiwarn-validationfailed-badchars": "caractères non valides dans la clé (<code>a-z</code>, <code>A-Z</code>, <code>0-9</code>, <code>_</code>et <code>-</code> sont les seuls autorisés).",
        "apiwarn-validationfailed-badpref": "pas une préférence valide.",
        "apiwarn-validationfailed-cannotset": "ne peut pas être initialisé par ce module.",
        "apiwarn-validationfailed-keytoolong": "clé trop longue (au plus $1 octets).",
+       "apiwarn-validationfailed": "Erreur de validation pour <kbd>$1</kbd>: $2",
+       "apiwarn-wgDebugAPI": "<strong>Avertissement de sécurité</strong>: <var>$wgDebugAPI</var> est activé.",
        "api-feed-error-title": "Erreur ($1)",
        "api-usage-docref": "Voir $1 concernant l'utilisation de l'API.",
        "api-exception-trace": "$1 à $2($3)\n$4",
index e688f8f..9e456bb 100644 (file)
        "apihelp-main-param-requestid": "Calquera valor dado aquí será incluído na resposta. Pode usarse para distingir peticións.",
        "apihelp-main-param-servedby": "Inclúa o nome do servidor que servía a solicitude nos resultados.",
        "apihelp-main-param-curtimestamp": "Incluir a marca de tempo actual no resultado.",
+       "apihelp-main-param-responselanginfo": "Incluír no resultado as linguas usada para <var>uselang</var> e <var>errorlang</var>.",
        "apihelp-main-param-origin": "Cando se accede á API usando unha petición AJAX entre-dominios (CORS), inicializar o parámetro co dominio orixe. Isto debe incluírse en calquera petición pre-flight, e polo tanto debe ser parte da petición URI (non do corpo POST). Para peticións autenticadas, isto debe coincidir exactamente cunha das orixes na cabeceira <code>Origin</code>, polo que ten que ser fixado a algo como <kbd>https://en.wikipedia.org</kbd> ou <kbd>https://meta.wikimedia.org</kbd>. Se este parámetro non coincide coa cabeceira <code>Origin</code>, devolverase unha resposta 403. Se este parámetro coincide coa cabeceira <code>Origin</code> e a orixe está na lista branca, as cabeceiras <code>Access-Control-Allow-Origin</code> e <code>Access-Control-Allow-Credentials</code> serán fixadas.\n\nPara peticións non autenticadas, especifique o valor <kbd>*</kbd>. Isto fará que se fixe a cabeceira <code>Access-Control-Allow-Origin</code>, pero <code>Access-Control-Allow-Credentials</code> será <code>false</code> e todos os datos específicos do usuario serán ocultados.",
        "apihelp-main-param-uselang": "Linga a usar para a tradución de mensaxes. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> con <kbd>siprop=languages</kbd> devolve unha lista de códigos de lingua, ou especificando <kbd>user</kbd> coa preferencia de lingua do usuario actual, ou especificando <kbd>content</kbd> para usar a lingua do contido desta wiki.",
+       "apihelp-main-param-errorformat": "Formato a usar para a saída do texto de aviso e de erroː\n; plaintext:  texto wiki sen as etiquetas HTML e coas entidades substituídas.\n; wikitext: texto wiki sen analizar.\n; html: HTML.\n; raw: Clave de mensaxe e parámetros.\n; none: Sen saída de texto, só os códigos de erro.\n; bc: Formato utilizado antes de MediaWiki 1.29. <var>errorlang</var> e <var>errorsuselocal</var> non se teñen en conta.",
        "apihelp-block-description": "Bloquear un usuario.",
        "apihelp-block-param-user": "Nome de usuario, dirección ou rango de IPs que quere bloquear.",
        "apihelp-block-param-expiry": "Tempo de caducidade. Pode ser relativo (p. ex.<kbd>5 meses</kbd> ou <kbd>2 semanas</kbd>) ou absoluto (p. ex. 2014-09-18T12:34:56Z</kbd>). Se se pon kbd>infinite</kbd>, <kbd>indefinite</kbd>, ou <kbd>never</kbd>, o bloqueo nunca caducará.",
        "api-help-authmanagerhelper-returnurl": "Devolve o URL para os fluxos de autenticación de terceiros, que debe ser absoluto. Este ou <var>$1continue</var> é obrigatorio.\n\nLogo da recepción dunha resposta <samp>REDIRECT</samp>, vostede normalmente abrirá un navegador web ou un visor web para ver a URL <samp>redirecttarget</samp> especificada para un fluxo de autenticación de terceiros. Cando isto se complete, a aplicación de terceiros enviará ó navegador web ou visor web a esta URL. Vostede debe eliminar calquera consulta ou parámetros POST da URL e pasalos como unha consulta <var>$1continue</var> a este módulo API.",
        "api-help-authmanagerhelper-continue": "Esta petición é unha continucación despois dun resposta precedente <samp>UI</samp> ou <samp>REDIRECT</samp>. Esta ou <var>$1returnurl</var> é requirida.",
        "api-help-authmanagerhelper-additional-params": "Este módulo acepta parámetros adicionais dependendo das consultas de autenticación dispoñibles. Use <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> con <kbd>amirequestsfor=$1</kbd> (ou unha resposta previa deste módulo, se aplicable) para determinar as consultas dispoñibles e os campos que usan.",
+       "apierror-articleexists": "O artigo que intentou crear xa existe.",
+       "apierror-badip": "O parámetro IP non é válido.",
+       "apierror-badmd5": "O código hash MD5 non era incorrecto.",
+       "apierror-badmodule-badsubmodule": "O módulo <kbd>$1</kbd> non ten un submódulo \"$2\".",
+       "apierror-badmodule-nosubmodules": "O módulo <kbd>$1</kbd> non ten submódulos.",
+       "apierror-badparameter": "Valor non válido para o parámetro <var>$1</var>.",
        "apierror-badquery": "A consulta non é válida.",
+       "apierror-badtimestamp": "Valor \"$2\" non válido para o parámetro de data e hora <var>$1</var>.",
+       "apierror-badtoken": "Identificador CSRF non válido.",
+       "apierror-badurl": "Valor \"$2\" non válido para o parámetro de URL <var>$1</var>.",
+       "apierror-baduser": "Valor \"$2\" non válido para o parámetro de usuario <var>$1</var>.",
        "apierror-blocked": "Foi bloqueado fronte á edición.",
        "apierror-botsnotsupported": "Esta interface non está dispoñible para bots.",
+       "apierror-cannotviewtitle": "Non está autorizado para ver $1.",
        "apierror-cantblock": "Non ten permisos para bloquear usuarios.",
        "apierror-cantimport": "Non ten permisos para importar páxinas.",
+       "apierror-changeauth-norequest": "Erro ó crear a petición de modificación.",
+       "apierror-chunk-too-small": "O tamaño mínimo dun segmento é de  $1 {{PLURAL:$1|byte|bytes}} para os segmentos non finais.",
+       "apierror-cidrtoobroad": "Os rangos CIDR $1 maiores que /$2 non son aceptados.",
+       "apierror-compare-inputneeded": "É necesario un título, un ID de páxina ou un número de revisión para os parámetros <var>from</var> e <var>to</var>.",
+       "apierror-contentserializationexception": "Erro de serialización do contidoː $1",
+       "apierror-contenttoobig": "O contido que achegou excede o límite de tamaño dun artigo, que é de  {{PLURAL:$1|kilobyte|kilobytes}}.",
+       "apierror-copyuploadbaddomain": "As subas por URL non están permitidas para este dominio.",
+       "apierror-copyuploadbadurl": "As subas non están permitidas para esta URL.",
+       "apierror-create-titleexists": "Os títulos existentes non poden ser protexidos con <kbd>create</kbd>.",
+       "apierror-csp-report": "Erro procesando o informe CSPː $1.",
+       "apierror-databaseerror": "[$1] erro de consulta da base de datos.",
+       "apierror-deletedrevs-param-not-1-2": "O parámetro <var>$1</var> non pode usarse nos modos 1 e 2.",
+       "apierror-deletedrevs-param-not-3": "O parámetro <var>$1</var> non pode usarse no modo 3.",
+       "apierror-emptynewsection": "Non é posible crear novas seccións baleiras.",
+       "apierror-emptypage": "Non é posible crear novas páxinas baleiras.",
+       "apierror-exceptioncaught": "[$1] Excepción capturada: $2",
        "apierror-filedoesnotexist": "O ficheiro non existe.",
+       "apierror-fileexists-sharedrepo-perm": "O ficheiro obxectivo existe nun servidor compartido. Use o parámetro <var>ignorewarnings</var> para ignoralo.",
+       "apierror-filenopath": "Non é posible obter o camiño do ficheiro local.",
+       "apierror-filetypecannotberotated": "O tipo de ficheiro non permite que sexa rotado.",
+       "apierror-formatphp": "Esta resposta non pode ser representada usando kbd>format=php</kbd>. Consulte https://phabricator.wikimedia.org/T68776.",
+       "apierror-imageusage-badtitle": "O título para <kbd>$1</kbd> debe ser un ficheiro.",
+       "apierror-import-unknownerror": "Erro descoñecido ó importarː $1.",
+       "apierror-integeroutofrange-abovebotmax": "<var>$1</var> non pode pasar de $2 (fixado a $3) para bots ou administradores do sistema.",
+       "apierror-integeroutofrange-abovemax": "<var>$1</var> non pode pasar de $2 (fixado a $3) para os usuarios.",
+       "apierror-integeroutofrange-belowminimum": "<var>$1</var> non pode ser menor de $2 (fixado a $3).",
+       "apierror-invalidcategory": "O nome da categoría que indicou non é válido.",
+       "apierror-invalid-chunk": "O desplazamento máis o segmento actual é maior que o tamaño solicitado do ficheiro.",
+       "apierror-invalidexpiry": "Hora de caducidade incorrecta \"$1\".",
+       "apierror-invalid-file-key": "Non se corresponde cunha clave válida de ficheiro.",
+       "apierror-invalidlang": "Código de lingua incorrecto para o parámetro <var>$1</var>.",
+       "apierror-invalidoldimage": "O parámetro oldimage ten un formato incorrecto.",
+       "apierror-invalidparammix-cannotusewith": "O parámetro <kbd>$1</kbd> non pode usarse xunto con <kbd>$2</kbd>.",
+       "apierror-invalidparammix-mustusewith": "O parámetro <kbd>$1</kbd> só pode usarse xunto con <kbd>$2</kbd>.",
+       "apierror-invalidparammix-parse-new-section": "<kbd>section=new</kbd> non se pode combinar cos parámetros <var>oldid</var>, <var>pageid</var> e <var>page</var>. Por favor, utilice <var>title</var> e <var>text</var>.",
+       "apierror-invalidparammix": "{{PLURAL:$2|Os parámetros}} $1 non poden usarse xuntos.",
+       "apierror-invalidsection": "O parámetro sección debe ser un ID de sección válido ou <kbd>new</kbd>.",
+       "apierror-invalidsha1base36hash": "O código hash SHA1Base36 proporcionado non é correcto.",
+       "apierror-invalidsha1hash": "O código hash SHA1 proporcionado non é correcto.",
+       "apierror-invalidtitle": "Título incorrecto \"$1\".",
+       "apierror-invalidurlparam": "Valor non válido para <var>$1urlparam</var> (<kbd>$2=$3</kbd>).",
+       "apierror-invaliduser": "Nome de usuario incorrecto \"$1\".",
+       "apierror-maxlag-generic": "Esparando por un servidor de base de datosː $1 {{PLURAL:$1|segundo|segundos}} de atraso.",
+       "apierror-maxlag": "Esperando por $2: $1 {{PLURAL:$1|segundo|segundos}} de atraso.",
+       "apierror-mimesearchdisabled": "A busca MIME está desactivada no modo Miser (tacaño).",
        "apierror-noedit-anon": "Os usuarios anónimos non poden editar páxinas.",
        "apierror-noedit": "Non ten permisos para editar páxinas.",
        "apierror-permissiondenied-generic": "Permisos rexeitados.",
index 6f6a84f..7f5b9d9 100644 (file)
@@ -29,7 +29,7 @@
        "apihelp-main-param-origin": "בעת גישה ל־API עם בקשת AJAX חוצה מתחמים (CORS), יש להציב כאן את המתחם שהבקשה יוצאת ממנו. זה היה להיות כלול בכל בקשה מקדימה, ולכן הוא חייב להיות חלק מה־URI של הבקשה (לא גוף ה־POST).\n\nעבור בקשות מאומתות, זה חייב להיות תואם במדויק לאחד המקורות בכותרת <code>Origin</code>, כך שזה צריך להיות מוגדר למשהו כמו <kbd>https://en.wikipedia.org</kbd> או <kbd>https://meta.wikimedia.org</kbd>. אם הפרמטר הזה אינו תואם לכותרת <code>Origin</code>, תוחזר תשובת 403. אם הפרמטר הזה תורם לכותרת <code>Origin</code> והמקור נמצא ברשימה הלבנה, תוגדרנה הכותרות <code>Access-Control-Allow-Origin</code> ו־<code>Access-Control-Allow-Credentials</code>.\n\nעבור בקשות בלתי־מאומתות, יש לציין את הערך <kbd>*</kbd>. זה יגרום לכותרת להיות <code>Access-Control-Allow-Origin</code>, אבל <code>Access-Control-Allow-Credentials</code> תהיה <code>false</code> וכל הנתונים הייחודיים למשתמש יהיו מוגבלים.",
        "apihelp-main-param-uselang": "באיזו שפה להשתמש לתרגומי הודעות. הקריאה <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> עם <kbd>siprop=languages</kbd> מחזירה רשימת קודים. ציון <kbd>user</kbd> כדי להשתמש בהעדפת השפה של המשתמש הנוכחי, וציון <kbd>content</kbd> להשתמש בקוד השפה של הוויקי הזה.",
        "apihelp-block-description": "חסימת משתמש.",
-       "apihelp-block-param-user": "שם משתמש, כתובת IP, או טווח IP שהנך רוצה לחסום.",
+       "apihelp-block-param-user": "שם משתמש, כתובת IP, או טווח כתובות IP שברצונך לחסום. אי־אפשר להשתמש בזה יחד עם <var>$1userid</var>",
        "apihelp-block-param-expiry": "זמן תפוגה. יכול להיות יחסי (למשל <kbd>5 months</kbd> או <kbd>2 weeks</kbd>) או מוחלט (למשל <kbd>2014-09-18T12:34:56Z</kbd>). אם זה מוגדר ל־<kbd>infinite</kbd>‏, <kbd>indefinite</kbd>, או <kbd>never</kbd>, החסימה לא תפוג לעולם.",
        "apihelp-block-param-reason": "סיבה לחסימה.",
        "apihelp-block-param-anononly": "לחסום משתמשים אלמוניים בלבד (דהיינו, השבתת עריכות אלמוניות מכתובת ה־IP הזאת)",
        "apihelp-tokens-example-edit": "אחזור אסימון עריכה (בררת המחדל).",
        "apihelp-tokens-example-emailmove": "אחזור אסימון דוא\"ל ואסימון העברה.",
        "apihelp-unblock-description": "שחרור משתמש מחסימה.",
-       "apihelp-unblock-param-id": "מזהה החסימה לשחרור (מתקבל דרך <kbd>list=blocks</kbd>). לא יכול לשמש יחד עם <var>$1user</var>.",
-       "apihelp-unblock-param-user": "שם משתמש, כתובת IP או טווח IP לחסימה. לא יכול לשמש יחד עם <var>$1id</var>",
+       "apihelp-unblock-param-id": "מזהה החסימה לשחרור (מתקבל דרך <kbd>list=blocks</kbd>). לא יכול לשמש יחד עם <var>$1user</var> או <var>$luserid</var>.",
+       "apihelp-unblock-param-user": "שם משתמש, כתובת IP או טווח כתובות IP לחסימה. לא יכול לשמש יחד עם <var>$1id</var> או <var>$luserid</var>.",
        "apihelp-unblock-param-reason": "סיבה להסרת חסימה.",
        "apihelp-unblock-param-tags": "תגי שינוי שיחולו על העיול ביומן החסימה.",
        "apihelp-unblock-example-id": "לשחרר את החסימה עם מזהה #<kbd>105</kbd>.",
index ea3f415..f790585 100644 (file)
@@ -15,7 +15,8 @@
                        "Urielejh",
                        "Matteocng",
                        "Einreiher",
-                       "Mpiva"
+                       "Mpiva",
+                       "Margherita.mignanelli"
                ]
        },
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Documentazione]] (in inglese)\n* [[mw:API:FAQ|FAQ]] (in inglese)\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Mailing list]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annunci sull'API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bug & richieste]\n</div>\n<strong>Stato:</strong> tutte le funzioni e caratteristiche mostrate su questa pagina dovrebbero funzionare, ma le API sono ancora in fase attiva di sviluppo, e potrebbero cambiare in qualsiasi momento. Iscriviti alla [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la mailing list sugli annunci delle API MediaWiki] per essere informato sugli aggiornamenti.\n\n<strong>Istruzioni sbagliate:</strong> quando vengono impartite alle API delle istruzioni sbagliate, un'intestazione HTTP verrà inviata col messaggio \"MediaWiki-API-Error\" e, sia il valore dell'intestazione, sia il codice d'errore, verranno impostati con lo stesso valore. Per maggiori informazioni leggi [[mw:API:Errors_and_warnings|API:Errori ed avvertimenti]] (in inglese).\n\n<strong>Test:</strong> per testare facilmente le richieste API, vedi [[Special:ApiSandbox]].",
@@ -26,7 +27,7 @@
        "apihelp-main-param-servedby": "Includi nel risultato il nome dell'host che ha servito la richiesta.",
        "apihelp-main-param-curtimestamp": "Includi nel risultato il timestamp attuale.",
        "apihelp-block-description": "Blocca  un utente.",
-       "apihelp-block-param-user": "Nome utente, indirizzo IP o range di IP da bloccare.",
+       "apihelp-block-param-user": "Nome utente, indirizzo IP o range di IP da bloccare. Non può essere usato insieme a <var>$1userid</var>",
        "apihelp-block-param-expiry": "Tempo di scadenza. Può essere relativo (ad esempio, <kbd>5 months</kbd> o <kbd>2 weeks</kbd>) o assoluto (ad esempio <kbd>2014-09-18T12:34:56Z</kbd>). Se impostato a <kbd>infinite</kbd>, <kbd>indefinite</kbd> o <kbd>never</kbd>, il blocco non scadrà mai.",
        "apihelp-block-param-reason": "Motivo del blocco.",
        "apihelp-block-param-anononly": "Blocca solo gli utenti non registrati (cioè disattiva i contributi anonimi da questo indirizzo IP).",
        "apihelp-tokens-param-type": "Tipi di token da richiedere.",
        "apihelp-tokens-example-edit": "Recupera un token di modifica (il predefinito).",
        "apihelp-unblock-description": "Sblocca un utente",
+       "apihelp-unblock-param-user": "Nome utente, indirizzo IP o range di IP da sbloccare. Non può essere usato insieme a <var>$1id</var> o <var>$luserid</var>.",
+       "apihelp-unblock-param-userid": "ID utente da sbloccare. Non può essere usato insieme a <var>$1id</var> o <var>$luserid</var>.",
        "apihelp-unblock-param-reason": "Motivo dello sblocco.",
        "apihelp-unblock-param-tags": "Modifica etichette da applicare all'elemento del registro dei blocchi.",
        "apihelp-undelete-param-title": "Titolo della pagina da ripristinare.",
        "apihelp-userrights-param-add": "Aggiungi l'utente a questi gruppi.",
        "apihelp-userrights-param-remove": "Rimuovi l'utente da questi gruppi.",
        "apihelp-userrights-param-reason": "Motivo del cambiamento.",
+       "apihelp-validatepassword-description": "Convalidare una password seguendo le politiche di wiki sulle password",
+       "apihelp-validatepassword-param-password": "Password da convalidare",
+       "apihelp-validatepassword-example-1": "Convalidare la password <kbd>foobar</kbd> per l'attuale utente.",
+       "apihelp-validatepassword-example-2": "Convalidare la password <kbd>qwerty</kbd> per la creazione di un utente <kbd>Esempio</kbd>.",
        "apihelp-watch-description": "Aggiunge o rimuove pagine dagli osservati speciali dell'utente attuale.",
        "apihelp-format-param-wrappedhtml": "Restituisce l'HTML ben formattato e i moduli ResourceLoader associati come un oggetto JSON.",
        "api-pageset-param-titles": "Un elenco di titoli su cui lavorare.",
        "api-help-authmanagerhelper-returnurl": "URL di ritorno per i flussi di autenticazione di terze parti, deve essere assoluto. E' necessario fornirlo, oppure va fornito <var>$1continue</var>.\n\nAlla ricezione di una risposta <samp>REDIRECT</samp>, in genere si apre un browser o una vista web all'URL specificato <samp>redirecttarget</samp> per un flusso di autenticazione di terze parti. Quando questo è completato, la terza parte invierà il browser o la vista web a questo URL. Dovresti estrarre qualsiasi parametro POST o della richiesta dall'URL e passarli come un request <var>$1continue</var> a questo modulo API.",
        "api-help-authmanagerhelper-continue": "Questa richiesta è una continuazione dopo una precedente risposta <samp>UI</samp> o <samp>REDIRECT</samp>. È necessario fornirlo, oppure fornire <var>$1returnurl</var>.",
        "api-help-authmanagerhelper-additional-params": "Questo modulo accetta parametri aggiuntivi a seconda delle richieste di autenticazione disponibili. Utilizza <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> con <kbd>amirequestsfor=$1</kbd> (o una precedente risposta da questo modulo, se applicabile) per determinare le richieste disponibili e i campi usati da queste.",
+       "apierror-nosuchuserid": "Non c'è alcun utente con ID $1.",
        "api-credits-header": "Crediti"
 }
index e5baedc..ff4f0d1 100644 (file)
@@ -30,7 +30,8 @@
        "apihelp-main-param-curtimestamp": "결과의 타임스탬프를 포함합니다.",
        "apihelp-main-param-uselang": "메시지 번역을 위한 언어입니다. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd>에 <kbd>siprop=languages</kbd>를 함께 사용하면 언어 코드의 목록을 반환하고, <kbd>user</kbd>를 지정하면 현재 사용자의 언어 환경 설정을 사용하며, <kbd>content</kbd>를 지정하면 이 위키의 콘텐츠 언어를 사용합니다.",
        "apihelp-block-description": "사용자를 차단합니다.",
-       "apihelp-block-param-user": "차단하고자 하는 계정 이름, IP 주소 또는 대역",
+       "apihelp-block-param-user": "차단할 사용자 이름, IP 주소, 또는 IP 주소 대역입니다. <var>$1userid</var>와(과) 함께 사용할 수 없습니다.",
+       "apihelp-block-param-userid": "차단할 사용자 ID입니다. <var>$1user</var>와(과) 함께 사용할 수 없습니다.",
        "apihelp-block-param-expiry": "기한. 상대값(예시: <kbd>5 months</kbd> 또는 </kbd>2 weeks</kbd>) 또는 절대값(예시: <kbd>2014-09-18T12:34:56Z</kbd>)이 될 수 있습니다. <kbd>infinite</kbd>, <kbd>indefinite</kbd> 또는 <kbd>never</kbd>로 설정하면 무기한으로 설정됩니다.",
        "apihelp-block-param-reason": "차단 이유.",
        "apihelp-block-param-anononly": "익명 사용자만 차단합니다. (즉, 이 IP의 익명 편집을 막음)",
        "apihelp-query+alldeletedrevisions-param-user": "이 사용자에 대한 판만 나열합니다.",
        "apihelp-query+alldeletedrevisions-param-excludeuser": "이 사용자에 대한 판을 나열하지 않습니다.",
        "apihelp-query+alldeletedrevisions-param-namespace": "이 이름공간의 문서만 나열합니다.",
+       "apihelp-query+alldeletedrevisions-example-user": "<kbd>Example</kbd>님의 최근 50개의 삭제된 기여를 나열합니다.",
        "apihelp-query+allfileusages-paramvalue-prop-title": "파일의 제목을 추가합니다.",
        "apihelp-query+allfileusages-param-limit": "반환할 총 항목 수입니다.",
        "apihelp-query+allfileusages-example-unique": "고유한 파일 제목을 나열합니다.",
        "apihelp-query+imageinfo-example-simple": "[[:File:Albert Einstein Head.jpg]]의 현재 판에 대한 정보를 가져옵니다.",
        "apihelp-query+imageinfo-example-dated": "2008년 및 그 이후의 [[:File:Test.jpg]]의 판에 대한 정보를 가져옵니다.",
        "apihelp-query+images-param-limit": "반환할 파일 수.",
+       "apihelp-query+images-example-simple": "[[Main Page|대문]]에 사용된 파일 목록을 가져옵니다.",
+       "apihelp-query+images-example-generator": "[[Main Page|대문]]에 사용된 모든 파일에 관한 정보를 가져옵니다.",
        "apihelp-query+imageusage-param-namespace": "열거할 이름공간.",
        "apihelp-query+imageusage-example-generator": "[[:File:Albert Einstein Head.jpg]]를 이용하여 페이지의 정보를 가져옵니다.",
        "apihelp-query+info-description": "기본 페이지 정보를 가져옵니다.",
        "apihelp-query+prefixsearch-param-limit": "반환할 결과의 최대 수",
        "apihelp-query+prefixsearch-param-profile": "검색 프로파일 사용",
        "apihelp-query+protectedtitles-paramvalue-prop-level": "보호 수준을 추가합니다.",
+       "apihelp-query+querypage-example-ancientpages": "[[Special:Ancientpages|특수기능:오래된문서]]에서 결과를 반환합니다.",
        "apihelp-query+recentchanges-param-prop": "추가 정보를 포함합니다:",
        "apihelp-query+recentchanges-paramvalue-prop-user": "편집에 임할 사용자를 추가하고 IP인 경우 태그합니다.",
        "apihelp-query+recentchanges-paramvalue-prop-userid": "편집에 임할 사용자를 추가합니다.",
        "apihelp-tag-param-reason": "변경 이유.",
        "apihelp-tokens-param-type": "요청할 토큰의 종류.",
        "apihelp-unblock-description": "사용자를 차단 해제합니다.",
+       "apihelp-unblock-param-user": "차단을 해제할 사용자 이름, IP 주소, IP 주소 대역입니다. <var>$1id</var> 또는 <var>$luserid</var>와(과) 함께 사용할 수 없습니다.",
+       "apihelp-unblock-param-userid": "차단을 해제할 사용자 ID입니다. <var>$1id</var> 또는 <var>$1user</var>와(과) 함께 사용할 수 없습니다.",
        "apihelp-unblock-param-reason": "차단 해제 이유.",
+       "apihelp-upload-param-ignorewarnings": "모든 경고를 무시합니다.",
        "apihelp-userrights-param-user": "사용자 이름.",
        "apihelp-userrights-param-userid": "사용자 ID.",
+       "apihelp-validatepassword-param-email": "계정 생성을 테스트할 때 사용할 이메일 주소입니다.",
+       "apihelp-validatepassword-param-realname": "계정 생성을 테스트할 때 사용할 실명입니다.",
        "apihelp-rawfm-description": "출력 데이터, 디버깅 요소를 포함, (HTML에 포함된)JSON형식.",
        "apihelp-xml-param-includexmlnamespace": "지정하면 XML 이름공간을 추가합니다.",
        "api-format-title": "미디어위키 API 결과",
        "api-help-param-type-integer": "유형: {{PLURAL:$1|1=정수|2=정수 목록}}",
        "api-help-param-type-boolean": "유형: 부울 ([[Special:ApiHelp/main#main/datatypes|자세한 정보]])",
        "api-help-param-type-user": "유형: {{PLURAL:$1|1=사용자 이름|2=사용자 이름 목록}}",
-       "api-help-param-list": "{{PLURAL:$1|1=다음 값 중 하나|2=값 (<kbd>{{!}}</kbd>로 구분)}}: $2",
+       "api-help-param-list": "{{PLURAL:$1|1=다음 값 중 하나|2=값 (<kbd>{{!}}</kbd>로 구분)}}: $2 또는 [[Special:ApiHelp/main#main/datatypes|alternative]]: $2",
        "api-help-param-list-can-be-empty": "{{PLURAL:$1|0=비어 있어야 함|비어 있을 수 있거나 $2}}",
        "api-help-param-limit": "$1 초과는 허용되지 않습니다.",
        "api-help-param-limit2": "$1 초과는 허용되지 않습니다. (봇의 경우 $2)",
        "apierror-autoblocked": "사용자의 IP 주소는 차단된 사용자에 의해 사용되었으므로 자동으로 차단된 상태입니다.",
        "apierror-badgenerator-unknown": "알 수 없는 <kbd>generator=$1</kbd>.",
        "apierror-badip": "IP 변수가 유효하지 않습니다.",
+       "apierror-badmd5": "제공된 MD5 해시가 잘못되었습니다.",
        "apierror-badmodule-badsubmodule": "<kbd>$1</kbd> 모듈에 \"$2\" 하위 모듈이 없습니다.",
        "apierror-badmodule-nosubmodules": "<kbd>$1</kbd> 모듈은 하위 모듈이 없습니다.",
        "apierror-badquery": "유효하지 않은 쿼리입니다.",
        "apierror-badtoken": "잘못된 CSRF 토큰.",
+       "apierror-blockedfrommail": "이메일 보내기에서 차단되어 있습니다.",
        "apierror-blocked": "편집에서 차단되어 있습니다.",
        "apierror-botsnotsupported": "이 인터페이스는 봇을 위해 지원되지 않습니다.",
        "apierror-cannotviewtitle": "$1을(를) 볼 권한이 없습니다.",
        "apierror-cantblock": "사용자를 차단할 권한이 없습니다.",
+       "apierror-canthide": "차단 기록에서 사용자 이름을 숨길 권한이 없습니다.",
        "apierror-cantimport-upload": "업로드된 페이지를 가져올 권한이 없습니다.",
+       "apierror-cantimport": "페이지를 가져올 권한이 없습니다.",
+       "apierror-cantsend": "로그인하지 않았거나 인증된 이메일 주소가 없거나 다른 사용자로 이메일을 보낼 권한이 없기 때문에 이메일을 보낼 수 없습니다.",
        "apierror-databaseerror": "[$1] 데이터베이스 쿼리 오류.",
        "apierror-emptynewsection": "비어있는 새 문단을 만들 수 없습니다.",
        "apierror-emptypage": "새 문서로 빈 문서를 만들 수 없습니다.",
        "apierror-invalidcategory": "입력한 분류 이름이 올바르지 않습니다.",
        "apierror-invalid-file-key": "유효한 파일 키가 아닙니다.",
        "apierror-invalidoldimage": "oldimage 변수에 유효하지 않은 형식이 있습니다.",
+       "apierror-invalidparammix-cannotusewith": "<kbd>$1</kbd> 변수는 <kbd>$2</kbd>와(과) 함께 사용할 수 없습니다.",
        "apierror-invalidsha1base36hash": "제공된 SHA1Base36 해시가 유효하지 않습니다.",
        "apierror-invalidsha1hash": "제공된 SHA1 해시가 유효하지 않습니다.",
        "apierror-invalidtitle": "잘못된 제목 \"$1\".",
        "apierror-invaliduser": "잘못된 사용자 이름 \"$1\".",
+       "apierror-maxlag-generic": "데이터베이스 서버 대기 중: $1 {{PLURAL:$1|초}} 지연되었습니다.",
+       "apierror-maxlag": "$2 대기 중: $1 {{PLURAL:$1|초}} 지연되었습니다.",
        "apierror-missingparam": "<var>$1</var> 변수는 설정해야 합니다.",
        "apierror-missingtitle": "지정한 페이지가 존재하지 않습니다.",
        "apierror-missingtitle-byname": "$1 문서가 존재하지 않습니다.",
        "apierror-mustbeloggedin-generic": "로그인해야 합니다.",
        "apierror-mustbeloggedin-linkaccounts": "계정을 연결하려면 로그인해야 합니다.",
        "apierror-mustbeloggedin": "$1에 로그인해야 합니다.",
+       "apierror-mustbeposted": "<kbd>$1</kbd> 모듈은 POST 요청이 필요합니다.",
        "apierror-noedit-anon": "익명 사용자는 문서를 편집할 수 없습니다.",
        "apierror-noedit": "문서를 편집할 권한이 없습니다.",
        "apierror-noimageredirect": "그림 넘겨주기를 만들 권한이 없습니다.",
        "apierror-nosuchrevid": "ID $1에 해당하는 판이 없습니다.",
+       "apierror-nosuchuserid": "ID $1에 해당하는 사용자가 없습니다.",
+       "apierror-notarget": "이 작업을 위한 유효한 대상을 지정하지 않았습니다.",
        "apierror-pagecannotexist": "이름공간은 실제 페이지를 허용하지 않습니다.",
        "apierror-permissiondenied": "$1에 대한 권한이 없습니다.",
        "apierror-permissiondenied-generic": "권한이 없습니다.",
        "apierror-permissiondenied-unblock": "사용자의 차단을 해제할 권한이 없습니다.",
        "apierror-protect-invalidaction": "잘못된 보호 유형 \"$1\".",
        "apierror-protect-invalidlevel": "잘못된 보호 수준 \"$1\".",
+       "apierror-ratelimited": "속도 제한을 초과했습니다. 잠시 기다렸다가 다시 시도하십시오.",
        "apierror-readapidenied": "이 모듈을 사용하려면 읽기 권한이 필요합니다.",
        "apierror-readonly": "위키는 현재 읽기 전용 모드입니다.",
        "apierror-revwrongpage": "r$1은(는) $2의 판이 아닙니다.",
        "apierror-specialpage-cantexecute": "특수 문서의 결과를 볼 권한이 없습니다.",
        "apierror-stashwrongowner": "잘못된 소유자: $1",
+       "apierror-systemblocked": "당신은 미디어위키에 의해서 자동으로 차단되었습니다.",
        "apierror-unknownerror-editpage": "알 수 없는 EditPage 오류: $1.",
        "apierror-unknownerror-nocode": "알 수 없는 오류.",
        "apierror-unknownerror": "알 수 없는 오류: \"$1\"",
        "apierror-unknownformat": "인식되지 않는 형식 \"$1\".",
        "apierror-unsupportedrepo": "로컬 파일 저장소는 모든 그림의 조회를 지원하지 않습니다.",
+       "apierror-upload-missingresult": "상태 데이터에 결과가 없습니다.",
        "apierror-writeapidenied": "API를 통해 이 위키를 편집할 권한이 없습니다.",
        "apiwarn-deprecation-httpsexpected": "HTTPS를 예측하였으나 HTTP가 사용되었습니다.",
        "apiwarn-difftohidden": "r$1에 대한 차이를 만들 수 없습니다: 내용이 숨겨져 있습니다.",
        "apiwarn-invalidcategory": "\"$1\"은(는) 분류가 아닙니다.",
        "apiwarn-invalidtitle": "\"$1\"은(는) 올바른 제목이 아닙니다.",
+       "apiwarn-invalidxmlstylesheetns": "스타일시트는 {{ns:MediaWiki}} 이름공간에 있어야 합니다.",
        "apiwarn-notfile": "\"$1\"은(는) 파일이 아닙니다.",
        "apiwarn-unsupportedarray": "<var>$1</var> 변수는 지원되지 않는 PHP 배열 문법을 사용합니다.",
        "apiwarn-validationfailed-keytoolong": "키가 너무 깁니다. ($1 바이트 이상 허용하지 않습니다)",
        "api-feed-error-title": "오류 ($1)",
+       "api-usage-docref": "API 사용법을 보려면 $1을(를) 참고하십시오.",
        "api-credits-header": "크레딧",
        "api-credits": "API 개발자:\n* Yuri Astrakhan (만든이, 선임 개발자 2006년 9월~2007년 9월)\n* Roan Kattouw (선임 개발자, 2007년 9월–2009년)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Brad Jorsch (선임 개발자 2013년–현재)\n\n당신의 의견이나 제안, 질문은 mediawiki-api@lists.wikimedia.org 로 보내주시고,\n버그 보고는 https://phabricator.wikimedia.org/ 에 해주시기 바랍니다."
 }
index 15b8f27..4a98f4a 100644 (file)
@@ -8,7 +8,7 @@
        "apihelp-main-param-assertuser": "Iwwerpréifen ob den aktuelle Benotzer de Benotzer mat deem Numm ass.",
        "apihelp-main-param-curtimestamp": "Den aktuellen Zäitstempel an d'Resultat integréieren.",
        "apihelp-block-description": "E Benotzer spären.",
-       "apihelp-block-param-user": "Benotzernumm, IP-Adress oder IP-Beräich deen Dir späre wëllt.",
+       "apihelp-block-param-user": "Benotzernumm, IP-Adress oder IP-Beräich fir ze spären. Kann net zesumme mat <var>$1userid</var> benotzt ginn.",
        "apihelp-block-param-reason": "Grond fir ze spären.",
        "apihelp-block-param-anononly": "Nëmmen anonym Benotzer spären (z. Bsp. anonym Ännerunge vun dëser IP-Adress ausschalten)",
        "apihelp-block-param-nocreate": "Opmaache vun engem Benotzerkont verhënneren.",
        "apihelp-userrights-param-user": "Benotzernumm.",
        "apihelp-userrights-param-userid": "Benotzer Id.",
        "apihelp-userrights-param-reason": "Grond fir d'Ännerung.",
+       "apihelp-validatepassword-param-password": "Passwuert fir ze validéieren.",
+       "apihelp-validatepassword-example-1": "Validéiert d'Passwuert <kbd>foobar</kbd> fir den aktuelle Benotzer.",
        "apihelp-watch-example-watch": "D'Säit <kbd>Main Page</kbd> iwwerwaachen.",
        "api-help-source": "Quell: $1",
        "api-help-source-unknown": "Quell: <span class=\"apihelp-unknown\">onbekannt</span>",
        "apierror-nochanges": "Et goufe keng Ännerungen ugefrot.",
        "apierror-nodeleteablefile": "Et gëtt keng esou al Versioun vum Fichier.",
        "apierror-noedit": "Dir hutt net déi néideg Rechter fir Säiten z'änneren.",
+       "apierror-nosuchuserid": "Et gëtt kee Benotzer mat der ID $1.",
        "apierror-notarget": "Dir hutt kee valabelt Zil fir dës Aktioun spezifizéiert.",
        "apierror-notpatrollable": "D'Versioun r$1 kann net nogekuckt gi well se ze al ass.",
        "apierror-pagecannotexist": "Nummraum erlaabt keng aktuell Säiten.",
        "apierror-readonly": "D'Wiki kann elo just geliest ginn.",
        "apierror-revwrongpage": "r$1 ass keng Versioun vu(n) $2.",
        "apierror-stashwrongowner": "Falsche Besëtzer: $1",
+       "apierror-systemblocked": "Dir gouft automatesch vu MediaWiki gespaart.",
        "apierror-unknownerror-editpage": "Onbekannten EditPage-Feeler: $1",
        "apierror-unknownerror-nocode": "Onbekannte Feeler.",
        "apierror-unknownerror": "Onbekannte Feeler: \"$1\".",
index b38e6a5..79c3e63 100644 (file)
        "apihelp-options-example-complex": "Nustatyti visus pageidavimus iš naujo, tada nustatyti <kbd>skin</kbd> ir <kbd>nickname</kbd>.",
        "apihelp-paraminfo-description": "Gauti informaciją apie API modulius.",
        "apihelp-protect-example-protect": "Apsaugoti puslapį.",
+       "apihelp-query-param-list": "Kurios sąrašus gauti.",
+       "apihelp-query-param-meta": "Kokius metaduomenis gauti.",
        "apihelp-query+allcategories-param-dir": "Rūšiavimo kryptis.",
        "apihelp-query+allcategories-param-min": "Gražinti tik kategorijas, kuriuose yra bent tiek narių.",
        "apihelp-query+allcategories-param-max": "Gražinti tik kategorijas, kuriuose yra iki tiek narių.",
        "apihelp-query+allcategories-param-limit": "Kiek kategorijų gražinti.",
        "apihelp-query+allcategories-paramvalue-prop-size": "Prideda puslapių kategorijoje skaičių.",
+       "apihelp-query+alldeletedrevisions-param-from": "Pradėti sąrašą šiuo pavadinimu.",
+       "apihelp-query+alldeletedrevisions-param-to": "Sustabdyti sąrašą ties šiuo pavadinimu.",
        "apihelp-query+alldeletedrevisions-example-user": "Sąrašas paskutinių 50 ištrintų indėlių pagal vartotoją\n<kbd>Pavyzdys</kbd>.",
        "apihelp-query+allfileusages-paramvalue-prop-title": "Prideda failo pavadinimą.",
        "apihelp-query+allfileusages-param-limit": "Kiek iš viso gražinti objektų.",
+       "apihelp-query+allfileusages-example-unique": "Pateikti unikalius failų pavadinimus.",
+       "apihelp-query+allfileusages-example-unique-generator": "Gauna visus failų pavadinimus, paženklinant trūkstamus.",
        "apihelp-query+allfileusages-example-generator": "Gauti puslapius, kuriuose yra failai.",
+       "apihelp-query+allimages-param-sort": "Pagal ką rūšiuoti.",
        "apihelp-query+allimages-param-limit": "Kiek iš viso gražinti paveikslėlių.",
        "apihelp-query+allimages-example-B": "Rodyti failų sąrašą, pradedant raide <kbd>B</kbd>.",
        "apihelp-query+allimages-example-recent": "Rodyti neseniai įkeltų failų sąrašą, panašu į [[Special:NewFiles]].",
        "apihelp-query+logevents-param-prop": "Kurias savybes gauti:",
        "apihelp-query+logevents-paramvalue-prop-ids": "Prideda žurnalo įvykio ID.",
        "apihelp-query+logevents-paramvalue-prop-type": "Prideda žurnalo įvykio tipą.",
+       "apihelp-query+transcludedin-paramvalue-prop-pageid": "Kiekvieno puslapio ID.",
+       "apihelp-query+transcludedin-paramvalue-prop-title": "Kiekvieno puslapio pavadinimas.",
+       "apihelp-query+transcludedin-param-limit": "Kiek gražinti.",
+       "apihelp-query+usercontribs-description": "Gauti visus vartotojo keitimus.",
+       "apihelp-query+usercontribs-param-limit": "Maksimalus gražinamų įnašų skaičius.",
+       "apihelp-query+usercontribs-paramvalue-prop-comment": "Prideda keitimo komentarą.",
+       "apihelp-query+usercontribs-paramvalue-prop-size": "Prideda naują keitimo dydį.",
+       "apihelp-query+userinfo-paramvalue-prop-realname": "Prideda vartotojo tikrą vardą.",
+       "apihelp-query+userinfo-example-simple": "Gauti informacijos apie dabartinį vartotoją.",
+       "apihelp-query+userinfo-example-data": "Gauti papildomos informacijos apie dabartinį vartotoją.",
+       "apihelp-query+users-description": "Gauti informacijos apie vartotojų sąrašą.",
+       "apihelp-query+users-param-prop": "Kokią informaciją įtraukti:",
+       "apihelp-query+users-paramvalue-prop-blockinfo": "Pažymi ar vartotojas užblokuotas, kas tai padarė ir dėl kokios priežasties.",
+       "apihelp-query+users-paramvalue-prop-groups": "Nurodo grupes, kurioms priklauso kiekvienas vartotojas.",
+       "apihelp-query+users-paramvalue-prop-implicitgroups": "Nurodo visas grupes, kuriuose vartotojas yra automatiškai kaip narys.",
+       "apihelp-query+users-paramvalue-prop-rights": "Nurodo visas teises, kurias turi kiekvienas vartotojas.",
+       "apihelp-query+users-paramvalue-prop-editcount": "Prideda vartotojo keitimų skaičių.",
+       "apihelp-query+users-paramvalue-prop-registration": "Prideda vartotojo registracijos laiko žymę.",
+       "apihelp-query+users-param-users": "Sąrašas vartotojų, kurių informaciją gauti.",
+       "apihelp-query+users-param-userids": "Vartotojų ID sąrašas, kurių informaciją gauti:",
+       "apihelp-query+users-param-token": "Vietoj to naudoti <kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>.",
+       "apihelp-query+users-example-simple": "Gražinti informaciją apie vartotoją <kbd>Example</kbd>.",
+       "apihelp-query+watchlist-param-user": "Nurodyti tik pakeitimus, atliktus šio vartotojo.",
+       "apihelp-query+watchlist-param-excludeuser": "Nenurodyti pakeitimų, kuriuos atliko šis vartotojas.",
+       "apihelp-query+watchlist-param-limit": "Kiek viso rezultatų gražinti vienai užklausai.",
+       "apihelp-query+watchlist-param-prop": "Kokias papildomas savybes gauti:",
+       "apihelp-query+watchlist-paramvalue-prop-title": "Prideda puslapio pavadinimą.",
+       "apihelp-query+watchlist-paramvalue-prop-user": "Prideda naują vartotoją, kuris atliko pakeitimą.",
+       "apihelp-query+watchlist-paramvalue-prop-userid": "Prideda vartotojo ID, kuris atliko pakeitimą.",
+       "apihelp-query+watchlist-paramvalue-prop-comment": "Prideda keitimo komentarą.",
+       "apihelp-query+watchlist-paramvalue-prop-timestamp": "Prideda keitimo laiko žymę.",
+       "apihelp-query+watchlist-paramvalue-prop-sizes": "Prideda naują ir seną puslapio ilgius.",
+       "apihelp-query+watchlist-paramvalue-prop-notificationtimestamp": "Prideda laiko žymę, kada vartotojui buvo pranešta apie pakeitimą.",
+       "apihelp-query+watchlist-paramvalue-prop-loginfo": "Prideda žurnalo informaciją, kai reikia.",
+       "apihelp-query+watchlist-param-type": "Kokios keitimų tipus rodyti:",
        "apihelp-query+watchlist-paramvalue-type-external": "Išoriniai keitimai.",
        "apihelp-query+watchlist-paramvalue-type-new": "Puslapio sukūrimai.",
+       "apihelp-query+watchlist-paramvalue-type-log": "Žurnalo įrašai.",
+       "apihelp-resetpassword-param-user": "Iš naujo nustatomas vartotojas.",
+       "apihelp-resetpassword-param-email": "Iš naujo nustatomo vartotojo el. pašto adresas.",
        "apihelp-stashedit-param-title": "Puslapio pavadinimas buvo redaguotas.",
        "apihelp-stashedit-param-sectiontitle": "Naujo skyriaus pavadinimas.",
        "apihelp-stashedit-param-text": "Puslapio turinys.",
+       "apihelp-stashedit-param-summary": "Keisti santrauką.",
+       "apihelp-tag-param-reason": "Keitimo priežastis.",
+       "apihelp-unblock-description": "Atblokuoti naudotoją.",
+       "apihelp-unblock-param-reason": "Atblokavimo priežastis.",
+       "apihelp-unblock-example-id": "Atblokuoti blokavimo ID #<kbd>105</kbd>.",
+       "apihelp-unblock-example-user": "Atblokuoti vartoją <kbd>Bob</kbd> su priežastimi <kbd>Sorry Bob</kbd>.",
+       "apihelp-undelete-param-title": "Atkuriamo puslapio pavadinimas.",
+       "apihelp-undelete-param-reason": "Atkūrimo priežastis.",
+       "apihelp-undelete-example-page": "Atkurti puslapį <kbd>Main Page</kbd>.",
+       "apihelp-upload-param-watch": "Stebėti šį puslapį.",
+       "apihelp-upload-param-ignorewarnings": "Ignuoruoti bet kokius įspėjimus.",
+       "apihelp-upload-param-file": "Failo turinys.",
+       "apihelp-upload-param-url": "URL, iš kurio gauti failą.",
+       "apihelp-upload-example-url": "Įkelti iš URL.",
+       "apihelp-upload-example-filekey": "Baigti įkėlimą, kuris nepavyko dėl įspėjimų.",
+       "apihelp-userrights-description": "Keisti vartotoju grupės narystę.",
+       "apihelp-userrights-param-user": "Vartotojo vardas.",
+       "apihelp-userrights-param-userid": "Vartotojo ID.",
+       "apihelp-userrights-param-add": "Pridėti vartotoją į šias grupes.",
+       "apihelp-userrights-param-remove": "Pašalinti vartotoją iš šių grupių.",
+       "apihelp-userrights-param-reason": "Keitimo priežastis.",
+       "apihelp-watch-description": "Pridėti ar pašalinti puslapius iš dabartinio vartotojo stebimųjų sąrašo.",
+       "apihelp-watch-example-watch": "Stebėti puslapį <kbd>Main Page</kbd>.",
+       "apihelp-watch-example-unwatch": "Nebestebėti puslapio <kbd>Main Page</kbd>.",
+       "api-format-title": "MedijaViki API rezultatas",
        "api-format-prettyprint-status": "Šis atsakymas būtų gražintas su HTTP statusu $1 $2.",
+       "api-help-title": "MedijaViki API pagalba",
+       "api-help-main-header": "Pagrindinis modulis",
+       "api-help-source": "Šaltinis: $1",
+       "api-help-source-unknown": "Šaltinis: <span class=\"apihelp-unknown\">nežinomas</span>",
+       "api-help-license": "Licencija: [[$1|$2]]",
+       "api-help-license-noname": "Licencija: [[$1|Žiūrėti nuorodą]]",
+       "api-help-license-unknown": "Licencija: <span class=\"apihelp-unknown\">nežinoma</span>",
+       "api-help-parameters": "{{PLURAL:$1|Parametras|Parametrai}}:",
+       "api-help-param-required": "Šis parametras yra reikalingas.",
+       "api-help-datatypes-header": "Duomenų tipai",
+       "api-help-param-limit": "Leidžiama ne daugiau nei $1.",
+       "api-help-param-limit2": "Leidžiama ne daugiau nei $1 ($2 robotams).",
+       "api-help-param-default": "Numatytasis: $1",
+       "api-help-param-default-empty": "Numatytasis: <span class=\"apihelp-empty\">(tuščia)</span>",
+       "api-help-param-no-description": "<span class=\"apihelp-empty\">(nėra aprašymo)</span>",
+       "api-help-examples": "{{PLURAL:$1|Pavyzdys|Pavyzdžiai}}:",
+       "api-help-permissions": "{{PLURAL:$1|Leidimas|Leidimai}}:",
+       "api-help-permissions-granted-to": "{{PLURAL:$1|Suteikta}}: $2",
        "apierror-articleexists": "Straipsnis, kurį bandėte sukurti, jau yra sukurtas.",
        "apierror-autoblocked": "Jūsų IP adresas buvo automatiškai užblokuotas, nes jis buvo naudojamas užblokuoto vartotojo.",
        "apierror-badgenerator-unknown": "Nežinomas <kbd>generator=$1</kbd>.",
        "apierror-badip": "IP parametras negalimas.",
+       "apierror-badquery": "Negalima užklausa.",
        "apierror-badurl": "Negalima reikšmė „$2“ URL parametrui <var>$1</var>.",
        "apierror-blockedfrommail": "Jus buvote užblokuotas nuo el. laiško siuntimo.",
+       "apierror-blocked": "Jus buvote užblokuotas nuo redagavimo.",
        "apierror-botsnotsupported": "Ši sąsaja negali būti palaikoma robotams.",
        "apierror-cannotreauthenticate": "Veiksmas negalimas, nes jūsų tapatybė negali būti patvirtinta.",
+       "apierror-cannotviewtitle": "Jūs negalite peržiūrėti $1.",
+       "apierror-cantblock": "Neturite teisės blokuoti vartotojus.",
+       "apierror-cantchangecontentmodel": "Neturite teisės pakeisti puslapio turinio modelį.",
+       "apierror-cantimport-upload": "Neturite teisės importuoti įkeltų puslapių.",
        "apierror-cantimport": "Neturite teisės importuoti puslapių.",
        "apierror-copyuploadbadurl": "Įkėlimas neleidžiamas iš šio URL.",
        "apierror-databaseerror": "[$1] Duomenų bazės užklausos klaida.",
        "apierror-emptynewsection": "Neįmanoma kurti naujų tuščių skyrių.",
+       "apierror-filedoesnotexist": "Failas neegzistuoja.",
        "apierror-filetypecannotberotated": "Failo tipas negali būti pasuktas.",
        "apierror-import-unknownerror": "Nežinoma klaida importuojant: $1.",
        "apierror-invalidcategory": "Kategorijos pavadinimas, kurį įvedėte, yra negalimas.",
        "apierror-multpages": "<var>$1</var> gali būti naudojamas tik su vienu puslapiu.",
        "apierror-mustbeloggedin-generic": "Turite būti prisijungęs.",
        "apierror-mustbeloggedin-linkaccounts": "Turite būti prisijungęs, kad galėtumėte susieti paskyras.",
+       "apierror-mustbeloggedin": "Turite būti prisijungęs, kad $1.",
        "apierror-nochanges": "Neprašyta jokių keitimų.",
+       "apierror-noedit-anon": "Anoniminiai vartotojai negali redaguoti puslapių.",
        "apierror-noedit": "Neturite teisės redaguoti puslapius.",
+       "apierror-nosuchlogid": "Nėra žurnalo įrašo su ID $1.",
+       "apierror-nosuchpageid": "Nėra puslapio su ID $1.",
+       "apierror-nosuchsection": "Nėra skyriaus $1.",
        "apierror-nosuchsection-what": "$2 nėra sekcijos $1.",
+       "apierror-nosuchuserid": "Nėra vartotojo su ID $1.",
        "apierror-paramempty": "Parametras <var>$1</var> negali būti tusčiau.",
        "apierror-permissiondenied": "Neturite leidimo $1.",
        "apierror-permissiondenied-generic": "Teisė nesuteikta.",
        "apiwarn-tokennotallowed": "Veiksmas „$1“ nėra leidžiamas dabartiniam vartotojui.",
        "apiwarn-validationfailed-badpref": "negalimas nustatymas.",
        "apiwarn-validationfailed": "Patvirtinimo klaida skirta <kbd>$1</kbd>: $2",
-       "api-feed-error-title": "Klaida ($1)"
+       "api-feed-error-title": "Klaida ($1)",
+       "api-credits-header": "Kreditai"
 }
index b163c22..6c90a3e 100644 (file)
@@ -9,5 +9,6 @@
        "apihelp-block-param-reason": "Bloķēšanas iemesls:",
        "apihelp-delete-description": "Dzēst lapas",
        "apihelp-emailuser-description": "Sūtīt e-pastu lietotājam",
-       "apihelp-userrights-param-userid": "Lietotāja ID:"
+       "apihelp-userrights-param-userid": "Lietotāja ID:",
+       "apierror-nosuchuserid": "Nav lietotāja ar ID $1."
 }
index 573c3f8..d3fc2f3 100644 (file)
@@ -29,7 +29,7 @@
        "apihelp-main-param-curtimestamp": "Dołącz obecny znacznik czasu do wyniku.",
        "apihelp-main-param-uselang": "Język, w którym mają być pokazywane tłumaczenia wiadomości. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> z <kbd>siprop=languages</kbd> zwróci listę języków lub ustaw jako <kbd>user</kbd>, aby pobrać z preferencji zalogowanego użytkownika lub <kbd>content</kbd>, aby wykorzystać język zawartości tej wiki.",
        "apihelp-block-description": "Zablokuj użytkownika.",
-       "apihelp-block-param-user": "Nazwa użytkownika, adres IP lub zakres adresów IP, które chcesz zablokować.",
+       "apihelp-block-param-user": "Nazwa użytkownika, adres IP albo zakres adresów IP, które chcesz zablokować. Nie można używać razem z <var>$1userid</var>.",
        "apihelp-block-param-expiry": "Czas trwania. Może być względny (np. <kbd>5 months</kbd> or <kbd>2 weeks</kbd>) lub konkretny (np. <kbd>2014-09-18T12:34:56Z</kbd>). Jeśli jest ustawiony na <kbd>infinite</kbd>, <kbd>indefinite</kbd>, lub <kbd>never</kbd>, blokada nigdy nie wygaśnie.",
        "apihelp-block-param-reason": "Powód blokady.",
        "apihelp-block-param-anononly": "Blokuj tylko anonimowych użytkowników (blokuje anonimowe edycje z tego adresu IP).",
        "apihelp-stashedit-param-text": "Zawartość strony.",
        "apihelp-tag-param-reason": "Powód zmiany.",
        "apihelp-unblock-description": "Odblokuj użytkownika.",
+       "apihelp-unblock-param-user": "Nazwa użytkownika, adres IP albo zakres adresów IP, które chcesz odblokować. Nie można używać jednocześnie z <var>$1id</var> lub <var>$luserid</var>.",
        "apihelp-unblock-param-reason": "Powód odblokowania.",
        "apihelp-undelete-param-reason": "Powód przywracania.",
        "apihelp-upload-param-filename": "Nazwa pliku docelowego.",
index 0c5cf8e..be62f8c 100644 (file)
@@ -27,7 +27,7 @@
        "apihelp-main-param-errorlang": "A língua a ser usada para avisos e erros. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> com <kbd>siprop=languages</kbd> devolve uma lista de códigos de língua, ou especifique <kbd>content</kbd> para usar a língua de conteúdo desta wiki, ou especifique <kbd>uselang</kbd> para usar o mesmo valor que o parâmetro <var>uselang</var>.",
        "apihelp-main-param-errorsuselocal": "Se fornecido, os textos de erro utilizarão mensagens personalizadas localmente do espaço nominal {{ns:MediaWiki}}.",
        "apihelp-block-description": "Bloquear um utilizador.",
-       "apihelp-block-param-user": "O nome de utilizador, endereço IP ou gama de endereços IP a serem bloqueados.",
+       "apihelp-block-param-user": "O nome de utilizador, endereço IP ou gama de endereços IP a serem bloqueados. Não pode ser usado em conjunto com <var>$1userid</var>",
        "apihelp-block-param-expiry": "O período de expiração. Pode ser relativo (p. ex. <kbd>5 meses</kbd> ou <kbd>2 semanas</kbd>) ou absoluto (p. ex. <kbd>2014-09-18T12:34:56Z</kbd>). Se definido como <kbd>infinite</kbd>, <kbd>indefinite</kbd> ou <kbd>never</kbd>, o bloqueio nunca expirará.",
        "apihelp-block-param-reason": "O motivo do bloqueio.",
        "apihelp-block-param-anononly": "Bloquear só utilizadores anónimos (isto é, impedir edições anónimas a partir deste endereço IP)",
        "apihelp-tokens-example-edit": "Obter uma chave de edição (padrão).",
        "apihelp-tokens-example-emailmove": "Obter uma chave de correio eletrónico e uma chave de movimentação.",
        "apihelp-unblock-description": "Desbloquear um utilizador.",
-       "apihelp-unblock-param-id": "Identificador do bloqueio a desfazer (obtido com <kbd>list=blocks</kbd>). Não pode ser usado em conjunto com <var>$1user</var>.",
-       "apihelp-unblock-param-user": "Nome de utilizador, endereço IP ou gama de endereços IP a desbloquear. Não pode ser usado em conjunto com <var>$1id</var>.",
+       "apihelp-unblock-param-id": "Identificador do bloqueio a desfazer (obtido com <kbd>list=blocks</kbd>). Não pode ser usado em conjunto com <var>$1user</var> ou <var>$luserid</var>.",
+       "apihelp-unblock-param-user": "O nome de utilizador, endereço IP ou gama de endereços IP a ser desbloqueado. Não pode ser usado em conjunto com <var>$1id</var> ou <var>$luserid</var>.",
        "apihelp-unblock-param-reason": "Motivo para o desbloqueio.",
        "apihelp-unblock-param-tags": "As etiquetas de modificação a aplicar à entrada no registo de bloqueios.",
        "apihelp-unblock-example-id": "Desfazer o bloqueio com o identificador #<kbd>105</kbd>.",
index 2a1c913..3c82486 100644 (file)
        "apihelp-query+imageinfo-paramvalue-prop-archivename": "{{doc-apihelp-paramvalue|query+imageinfo|prop|archivename}}",
        "apihelp-query+imageinfo-paramvalue-prop-bitdepth": "{{doc-apihelp-paramvalue|query+imageinfo|prop|bitdepth}}",
        "apihelp-query+imageinfo-paramvalue-prop-uploadwarning": "{{doc-apihelp-paramvalue|query+imageinfo|prop|uploadwarning}}",
+       "apihelp-query+imageinfo-paramvalue-prop-badfile": "{{doc-apihelp-paramvalue|query+imageinfo|prop|badfile}}",
        "apihelp-query+imageinfo-param-limit": "{{doc-apihelp-param|query+imageinfo|limit}}",
        "apihelp-query+imageinfo-param-start": "{{doc-apihelp-param|query+imageinfo|start}}",
        "apihelp-query+imageinfo-param-end": "{{doc-apihelp-param|query+imageinfo|end}}",
        "apihelp-query+imageinfo-param-extmetadatamultilang": "{{doc-apihelp-param|query+imageinfo|extmetadatamultilang}}",
        "apihelp-query+imageinfo-param-extmetadatafilter": "{{doc-apihelp-param|query+imageinfo|extmetadatafilter}}",
        "apihelp-query+imageinfo-param-urlparam": "{{doc-apihelp-param|query+imageinfo|urlparam}}",
+       "apihelp-query+imageinfo-param-badfilecontexttitle": "{{doc-apihelp-param|query+imageinfo|badfilecontexttitle}}",
        "apihelp-query+imageinfo-param-localonly": "{{doc-apihelp-param|query+imageinfo|localonly}}",
        "apihelp-query+imageinfo-example-simple": "{{doc-apihelp-example|query+imageinfo}}",
        "apihelp-query+imageinfo-example-dated": "{{doc-apihelp-example|query+imageinfo}}",
        "apihelp-userrights-param-reason": "{{doc-apihelp-param|userrights|reason}}",
        "apihelp-userrights-example-user": "{{doc-apihelp-example|userrights}}",
        "apihelp-userrights-example-userid": "{{doc-apihelp-example|userrights}}",
+       "apihelp-validatepassword-description": "{{doc-apihelp-description|validatepassword}}",
+       "apihelp-validatepassword-param-password": "{{doc-apihelp-param|validatepassword|password}}",
+       "apihelp-validatepassword-param-user": "{{doc-apihelp-param|validatepassword|user}}",
+       "apihelp-validatepassword-param-email": "{{doc-apihelp-param|validatepassword|email}}",
+       "apihelp-validatepassword-param-realname": "{{doc-apihelp-param|validatepassword|realname}}",
+       "apihelp-validatepassword-example-1": "{{doc-apihelp-example|validatepassword}}",
+       "apihelp-validatepassword-example-2": "{{doc-apihelp-example|validatepassword}}",
        "apihelp-watch-description": "{{doc-apihelp-description|watch}}",
        "apihelp-watch-param-title": "{{doc-apihelp-param|watch|title}}",
        "apihelp-watch-param-unwatch": "{{doc-apihelp-param|watch|unwatch}}",
        "api-help-param-deprecated": "Displayed in the API help for any deprecated parameter\n{{Identical|Deprecated}}",
        "api-help-param-required": "Displayed in the API help for any required parameter",
        "api-help-datatypes-header": "Header for the data type section in the API help output",
-       "api-help-datatypes": "{{technical}} {{doc-important|Do not translate or reformat dates inside &lt;kbd&gt; tags}} Documentation of certain API data types\nSee also:\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
+       "api-help-datatypes": "{{technical}} {{doc-important|Do not translate or reformat dates inside <nowiki><kbd></kbd></nowiki> or <nowiki><var></var></nowiki> tags}} Documentation of certain API data types\nSee also:\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "api-help-param-type-limit": "{{technical}} {{doc-important|Do not translate text inside &lt;kbd&gt; tags}} Used to indicate that a parameter is a \"limit\" type. Parameters:\n* $1 - Always 1.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "api-help-param-type-integer": "{{technical}} Used to indicate that a parameter is an integer or list of integers. Parameters:\n* $1 - 1 if the parameter takes one value, 2 if the parameter takes a list of values.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "api-help-param-type-boolean": "{{technical}} {{doc-important|Do not translate <code>Special:ApiHelp</code> in this message.}} Used to indicate that a parameter is a boolean. Parameters:\n* $1 - Always 1.\nSee also:\n* {{msg-mw|api-help-datatypes}}\n* [[Special:PrefixIndex/MediaWiki:api-help-param-type]]",
        "apierror-specialpage-cantexecute": "{{doc-apierror}}",
        "apierror-stashedfilenotfound": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
        "apierror-stashedit-missingtext": "{{doc-apierror}}",
+       "apierror-stashexception": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. May be English or localized, may or may not end in punctuation.",
        "apierror-stashfailed-complete": "{{doc-apierror}}",
        "apierror-stashfailed-nosession": "{{doc-apierror}}",
        "apierror-stashfilestorage": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text, which may already end with punctuation. Currently this is probably English, hopefully we'll fix that in the future.",
+       "apierror-stashinvalidfile": "{{doc-apierror}}",
        "apierror-stashnosuchfilekey": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
        "apierror-stashpathinvalid": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
        "apierror-stashwrongowner": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text, which should already end with punctuation. Currently this is probably English, hopefully we'll fix that in the future.",
        "apierror-stashzerolength": "{{doc-apierror}}\n\nParameters:\n* $1 - Exception text. Currently this is probably English, hopefully we'll fix that in the future.",
+       "apierror-systemblocked": "{{doc-apierror}}",
        "apierror-templateexpansion-notwikitext": "{{doc-apierror}}\n\nParameters:\n* $1 - Page title.\n* $2 - Content model.",
        "apierror-toofewexpiries": "{{doc-apierror}}\n\nParameters:\n* $1 - Number provided.\n* $2 - Number needed.",
        "apierror-unknownaction": "{{doc-apierror}}\n\nParameters:\n* $1 - Action provided.",
index 2879020..321731c 100644 (file)
@@ -26,7 +26,7 @@
        "apihelp-main-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:API:Main_page|Документация]]\n* [[mw: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> Все отображаемые на этой странице функции должны работать, однако API находится в статусе активной разработки и может измениться в любой момент. Подпишитесь на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ почтовую рассылку mediawiki-api-announce], чтобы быть в курсе обновлений.\n\n<strong>Ошибочные запросы:</strong> Если API получает запрос с ошибкой, вернётся заголовок HTTP с ключом «MediaWiki-API-Error», после чего значение заголовка и код ошибки будут отправлены обратно и установлены в то же значение. Более подробную информацию см. [[mw:API:Errors_and_warnings|API: Ошибки и предупреждения]].\n\n<strong>Тестирование:</strong> для удобства тестирования API-запросов, см. [[Special:ApiSandbox]].",
        "apihelp-main-param-action": "Действие, которое следует выполнить.",
        "apihelp-main-param-format": "Формат вывода.",
-       "apihelp-main-param-maxlag": "Ð\9cакÑ\81ималÑ\8cное Ð¾Ñ\82Ñ\81Ñ\82авание Ð¼Ð¾Ð¶ÐµÑ\82 Ð±Ñ\8bÑ\82Ñ\8c Ð¸Ñ\81полÑ\8cзован, ÐºÐ¾Ð³Ð´Ð° Ð\9cедиавики Ñ\83Ñ\81Ñ\82анавливаеÑ\82Ñ\81Ñ\8f Ð½Ð° Ñ\80еплиÑ\86иÑ\80Ñ\83емой Ð±Ð°Ð·Ñ\8b Ð´Ð°Ð½Ð½Ñ\8bÑ\85 ÐºÐ»Ð°Ñ\81Ñ\82еÑ\80а. Ð§Ñ\82обÑ\8b Ñ\81паÑ\81Ñ\82и Ð´ÐµÐ¹Ñ\81Ñ\82вий, Ñ\81поÑ\81обнÑ\8bÑ\85 Ð¿Ñ\80иÑ\87иниÑ\82Ñ\8c Ð±Ð¾Ð»Ñ\8cÑ\88е Ð¾Ñ\82Ñ\81Ñ\82аваÑ\82Ñ\8c Ñ\80епликаÑ\86ии Ñ\81айÑ\82а, Ñ\8dÑ\82оÑ\82 Ð¿Ð°Ñ\80амеÑ\82Ñ\80 Ð¼Ð¾Ð¶ÐµÑ\82 Ð·Ð°Ñ\81Ñ\82авлÑ\8fÑ\82Ñ\8c ÐºÐ»Ð¸ÐµÐ½Ñ\82а Ð¶Ð´Ð°Ñ\82Ñ\8c Ð´Ð¾ Ð·Ð°Ð´ÐµÑ\80жки Ñ\80епликаÑ\86ии Ð¼ÐµÐ½Ñ\8cÑ\88е Ñ\83казанного Ð·Ð½Ð°Ñ\87ениÑ\8f. Ð\92 Ñ\81лÑ\83Ñ\87ае Ñ\87Ñ\80езмеÑ\80ной Ð·Ð°Ð´ÐµÑ\80жки, ÐºÐ¾Ð´ Ð¾Ñ\88ибки <samp>maxlag</samp> Ð²Ð¾Ð·Ð²Ñ\80аÑ\89аеÑ\82Ñ\81Ñ\8f Ñ\81 Ñ\81ообÑ\89ением <samp>ждеÑ\82 $ведÑ\83Ñ\89ий: $оÑ\82Ñ\81Ñ\82аваÑ\82Ñ\8c Ñ\81екÑ\83нд Ð¾Ñ\82Ñ\81Ñ\82ала</samp>.<br />См. [[mw:Manual:Maxlag_parameter|Maxlag Ð¿Ð°Ñ\80амеÑ\82Ñ\80]] Ð´Ð»Ñ\8f Ð¿Ð¾Ð»Ñ\83Ñ\87ениÑ\8f Ð´Ð¾Ð¿Ð¾Ð»Ð½Ð¸Ñ\82елÑ\8cной Ð¸Ð½Ñ\84оÑ\80маÑ\86ии.",
+       "apihelp-main-param-maxlag": "Ð\97наÑ\87ение Ð¼Ð°ÐºÑ\81ималÑ\8cного Ð¾Ñ\82Ñ\81Ñ\82аваниÑ\8f Ð¼Ð¾Ð¶ÐµÑ\82 Ð¸Ñ\81полÑ\8cзоваÑ\82Ñ\8cÑ\81Ñ\8f, ÐºÐ¾Ð³Ð´Ð° MediaWiki Ñ\83Ñ\81Ñ\82анавливаеÑ\82Ñ\81Ñ\8f Ð½Ð° ÐºÐ»Ð°Ñ\81Ñ\82еÑ\80 Ð¸Ð· Ñ\80еплиÑ\86иÑ\80Ñ\83емÑ\8bÑ\85 Ð±Ð°Ð· Ð´Ð°Ð½Ð½Ñ\8bÑ\85. Ð§Ñ\82обÑ\8b Ð¸Ð·Ð±ÐµÐ¶Ð°Ñ\82Ñ\8c Ñ\83Ñ\85Ñ\83дÑ\88ениÑ\8f Ñ\81иÑ\82Ñ\83аÑ\86ии Ñ\81 Ð¾Ñ\82Ñ\81Ñ\82аванием Ñ\80епликаÑ\86ии Ñ\81айÑ\82а, Ñ\8dÑ\82оÑ\82 Ð¿Ð°Ñ\80амеÑ\82Ñ\80 Ð¼Ð¾Ð¶ÐµÑ\82 Ð·Ð°Ñ\81Ñ\82авиÑ\82Ñ\8c ÐºÐ»Ð¸ÐµÐ½Ñ\82а Ð¶Ð´Ð°Ñ\82Ñ\8c, ÐºÐ¾Ð³Ð´Ð° Ð·Ð°Ð´ÐµÑ\80жка Ñ\80епликаÑ\86ии Ñ\81Ñ\82анеÑ\82 Ð½Ð¸Ð¶Ðµ Ñ\83казанного Ð·Ð½Ð°Ñ\87ениÑ\8f. Ð\92 Ñ\81лÑ\83Ñ\87ае Ñ\87Ñ\80езмеÑ\80ной Ð·Ð°Ð´ÐµÑ\80жки Ð²Ð¾Ð·Ð²Ñ\80аÑ\89аеÑ\82Ñ\81Ñ\8f ÐºÐ¾Ð´ Ð¾Ñ\88ибки Â«<samp>maxlag</samp>» Ñ\81 Ñ\81ообÑ\89ением Â«<samp>Waiting for $host: $lag seconds lagged</samp>».<br />См. Ð¿Ð¾Ð´Ñ\80обнее Ð½Ð° Ñ\81Ñ\82Ñ\80аниÑ\86е Ñ\81 Ð¾Ð¿Ð¸Ñ\81анием [[mw:Manual:Maxlag_parameter|паÑ\80амеÑ\82Ñ\80а maxlag]].",
        "apihelp-main-param-smaxage": "Устанавливает значение HTTP-заголовка Cache-Control <code>s-maxage</code> в заданное число секунд. Ошибки никогда не кэшируются.",
        "apihelp-main-param-maxage": "Устанавливает значение HTTP-заголовка Cache-Control <code>s-maxage</code> в заданное число секунд. Ошибки никогда не кэшируются.",
        "apihelp-main-param-assert": "Удостовериться, что пользователь авторизован, если задано <kbd>user</kbd>, или что имеет права бота, если задано <kbd>bot</kbd>.",
        "apihelp-main-param-servedby": "Включить в результаты имя хоста, обработавшего запрос.",
        "apihelp-main-param-curtimestamp": "Включить в результаты временную метку.",
        "apihelp-main-param-origin": "При обращении к API, используя кросс-доменный AJAX-запрос (CORS), задайте параметру значение исходного домена. Он должен быть включён в любой предварительный запрос и таким образом должен быть частью URI-запроса (не тела POST).\n\nДля аутентифицированных запросов он должен точно соответствовать одному из источников в заголовке <code>Origin</code>, так что он должен быть задан наподобие <kbd>https://ru.wikipedia.org</kbd> или <kbd>https://meta.wikimedia.org</kbd>. Если параметр не соответствует заголовку <code>Origin</code>, будет возвращён ответ с кодом ошибки 403. Если параметр соответствует заголовку <code>Origin</code>, и источник находится в белом списке, будут установлены заголовки <code>Access-Control-Allow-Origin</code> и <code>Access-Control-Allow-Credentials</code>.\n\nДля неаутентифицированных запросов укажите значение <kbd>*</kbd>. Это приведёт к установке заголовка <code>Access-Control-Allow-Origin</code> заголовка должен быть установлен, но <code>Access-Control-Allow-Credentials</code> примет значение <code>false</code> и все пользовательские данные будут ограничены.",
-       "apihelp-main-param-uselang": "Язык, используемый для перевода Сообщений. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> с <kbd>siprop=языки</kbd> возвращает список кодов языков, или указать <kbd>пользователей</kbd> , чтобы использовать текущий язык пользователя предпочтения, или указать <kbd>контента</kbd> для использования этой Вики содержание язык.",
+       "apihelp-main-param-uselang": "Язык, используемый для перевода сообщений. Запрос «<kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd>» с «<kbd>siprop=languages</kbd>» возвращает список кодов языков; укажите «<kbd>user</kbd>», чтобы использовать текущие языковые настройки пользователя, или «<kbd>content</kbd>» для использования основного языка этой вики.",
+       "apihelp-main-param-errorlang": "Язык, используемый для вывода предупреждений и сообщений об ошибках. Запрос «<kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd>» с «<kbd>siprop=languages</kbd>» возвращает список кодов языков; укажите «<kbd>content</kbd>» для использования основного языка этой вики, или «<kbd>uselang</kbd>» для использования того же значения, что и в параметре «<var>uselang</var>».",
        "apihelp-block-description": "Блокировка участника.",
-       "apihelp-block-param-user": "Имя участника, IP-адрес или диапазон IP-адресов, которые вы хотите заблокировать.",
+       "apihelp-block-param-user": "Имя участника, IP-адрес или диапазон IP-адресов, которые вы хотите заблокировать. Нельзя использовать вместе с <var>$1userid</var>",
+       "apihelp-block-param-userid": "ID участника, которого вы хотите заблокировать. Нельзя использовать одновременно с <var>$1user</var>.",
        "apihelp-block-param-expiry": "Время истечения срока действия. Могут быть относительными (например, <kbd>5 месяцев</kbd> или <kbd>2 недели</kbd>) или абсолютными (например, <kbd>2014-09-18T12:34:56Z</kbd>). Если задано <kbd>бессрочно</kbd>, <kbd>бессрочно</kbd>, или <kbd>не</kbd>, блок никогда не истекает.",
        "apihelp-block-param-reason": "Причина блокировки.",
        "apihelp-block-param-anononly": "Блокировать только анонимных пользователей (т. е. запретить анонимные правки для этого IP-адреса).",
        "apihelp-query+deletedrevs-example-mode1": "Юҡ ителгән һуңғы биттәрҙең исемлеге, баш биттең<kbd>-һы </kbd> һәм<kbd>әйтергә:баш биттең /kbd>-һы,континент менән(режим 1).",
        "apihelp-query+deletedrevs-example-mode3-talk": "Юҡ ителгән тәүге 50 биттең исемлеге {{НС:фекер алышыу}} исемдәр арауығы(режим 3).",
        "apihelp-query+duplicatefiles-example-generated": "Поиск дубликатов всех файлов.",
+       "apihelp-query+imageinfo-paramvalue-prop-badfile": "Добавляет указание на то, находится ли файл в списке [[MediaWiki:Bad image list]]",
        "apihelp-query+logevents-description": "Получать события из журналов.",
        "apihelp-query+logevents-example-simple": "Список последних зарегистрированных событий.",
        "apihelp-query+pagepropnames-example-simple": "Получить первые 10 имен свойств.",
        "apihelp-revisiondelete-description": "удалить и восстановить редакции",
        "apihelp-stashedit-param-sectiontitle": "Заголовок нового раздела.",
        "apihelp-unblock-description": "Разблокировать пользователя.",
+       "apihelp-unblock-param-user": "Имя участника, IP-адрес или диапазон IP-адресов, которые вы хотите разблокировать. Нельзя использовать одновременно с <var>$1id</var> или <var>$luserid</var>.",
+       "apihelp-unblock-param-userid": "ID участника, которого вы хотите разблокировать. Нельзя использовать одновременно с <var>$1id</var> или <var>$1user</var>.",
        "apihelp-unblock-param-reason": "Причина разблокировки",
        "apihelp-unblock-example-id": "Разблокировать блок с идентификатором #<kbd>105</kbd>.",
        "apihelp-unblock-example-user": "Разблокировать пользователя <kbd>Bob</kbd> по причине <kbd>Sorry Bob</kbd>.",
        "api-help-examples": "Пример{{PLURAL:$1||ы}}:",
        "api-help-permissions": "{{PLURAL:$1|Permission|Permissions}}:",
        "api-help-permissions-granted-to": "{{PLURAL:$1|Granted to}}: $2",
+       "apierror-integeroutofrange-abovemax": "<var>$1</var> не может быть более $2 (на $3) для пользователей.",
+       "apierror-nosuchuserid": "Нет пользователя с ID $1.",
+       "apierror-protect-invalidaction": "Недопустимый тип защиты \"$1\".",
+       "apierror-systemblocked": "Вы были заблокированы автоматически Медиавики.",
+       "apierror-unknownformat": "Неизвестный Формат \"$1\".",
+       "apierror-urlparamnormal": "Не могли нормализовать параметры изображения для $1.",
        "api-credits-header": "Создатели"
 }
index b3253a5..ece0818 100644 (file)
@@ -29,7 +29,8 @@
        "apihelp-main-param-origin": "När API:et används genom en cross-domain AJAX-begäran (CORS), ange detta till den ursprungliga domänen. Detta måste inkluderas i alla pre-flight-begäran, och mpste därför vara en del av den begärda URI:n (inte i POST-datat). Detta måste överensstämma med en av källorna i headern <code>Origin</code> exakt, så den måste sättas till något i stil med <kbd>http://en.wikipedia.org</kbd> eller <kbd>https://meta.wikimedia.org</kbd>. Om denna parameter inte överensstämmer med headern <code>Origin</code>, returneras ett 403-svar. Om denna parameter överensstämmer med headern <code>Origin</code> och källan är vitlistad, sätts en <code>Access-Control-Allow-Origin</code>-header.",
        "apihelp-main-param-uselang": "Språk som ska användas för meddelandeöversättningar. En lista med koder kan hämtas från <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> med <kbd>siprop=languages</kbd>, eller ange <kbd>user</kbd> för att använda den aktuella användarens språkpreferenser, eller ange <kbd>content</kbd> för att använda innehållsspråket.",
        "apihelp-block-description": "Blockera en användare.",
-       "apihelp-block-param-user": "Användare, IP-adress eller IP-intervall du vill blockera.",
+       "apihelp-block-param-user": "Användare, IP-adress eller IP-intervall att blockera. Kan inte användas tillsammans med <var>$1userid</var>",
+       "apihelp-block-param-userid": "Användar-ID att blocker. Kan inte användas tillsammans med <var>$1user</var>.",
        "apihelp-block-param-expiry": "Förfallotid. Kan vara Kan vara relativt (t.ex. <kbd>5 months</kbd> eller <kbd>2 weeks</kbd>) eller absolut (t.ex. <kbd>2014-09-18T12:34:56Z</kbd>). Om satt till <kbd>infinite</kbd>, <kbd>indefinite</kbd> eller <kbd>never</kbd>, kommer blockeringen aldrig att löpa ut.",
        "apihelp-block-param-reason": "Orsak till blockering.",
        "apihelp-block-param-anononly": "Blockera endast anonyma användare (t.ex. inaktivera anonyma redigeringar för denna IP-adress).",
        "apihelp-query+watchlistraw-example-simple": "Lista sidor på den aktuella användarens bevakningslista.",
        "apihelp-setnotificationtimestamp-example-all": "Återställ meddelandestatus för hela bevakningslistan.",
        "apihelp-stashedit-param-summary": "Ändra sammanfattning.",
+       "apihelp-unblock-param-id": "ID för blockeringen att häva (hämtas genom <kbd>list=blocks</kbd>). Kan inte användas tillsammans med <var>$1user</var> eller <var>$luserid</var>.",
+       "apihelp-unblock-param-user": "Användarnamn, IP-adresser eller IP-adressintervall att häva blockering för. Kan inte användas tillsammans med <var>$1id</var> eller <var>$luserid</var>.",
+       "apihelp-unblock-param-userid": "Användar-ID att häva blockering för. Kan inte användas tillsammans med <var>$1id</var> eller <var>$1user</var>.",
        "apihelp-upload-param-filekey": "Nyckel som identifierar en tidigare uppladdning som lagrats temporärt.",
        "apihelp-upload-param-stash": "Om angiven, kommer servern att temporärt lagra filen istället för att lägga till den i centralförvaret.",
        "apihelp-upload-example-url": "Ladda upp från URL.",
        "api-help-param-limit2": "Inte mer än $1 ($2 för robotar) tillåts.",
        "api-help-param-multi-separate": "Separera värden med <kbd>|</kbd> eller [[Special:ApiHelp/main#main/datatypes|alternativ]].",
        "apierror-articleexists": "Artikeln du försökte skapa har redan skapats.",
+       "apierror-nosuchuserid": "Det finns ingen användare med ID $1.",
        "apierror-protect-invalidaction": "Ogiltig skyddstyp \"$1\".",
+       "apierror-systemblocked": "Du har blockerats automatiskt av MediaWiki.",
        "apierror-unknownformat": "Okänt format \"$1\".",
        "api-feed-error-title": "Fel ($1)"
 }
index fe9d085..9aaba31 100644 (file)
@@ -1,9 +1,11 @@
 {
        "@metadata": {
                "authors": [
-                       "Kaganer"
+                       "Kaganer",
+                       "Mouse21"
                ]
        },
+       "apihelp-block-description": "Блокировка пыриськисьёс.",
        "apihelp-edit-example-edit": "Бамез тупатъяно.",
        "apihelp-login-example-login": "Пырыны."
 }
index a823a00..aaea10a 100644 (file)
        "apihelp-main-param-origin": "При доступі до API з використанням крос-доменного AJAX-запиту (CORS), задайте параметру значення вихідного домена. Він має бути включений у будь-який попередній запит і таким чином мусить бути частиною запиту URI (не тіла POST). \n\nДля автентифікованих запитів він повинен точно співпадати з одним з виходів у заголовку <code>Origin</code>, тобто бути заданим чимось на зразок <kbd>https://uk.wikipedia.org</kbd> або <kbd>https://meta.wikimedia.org</kbd>. Якщо цей параметр не співпадає з заголовком <code>Origin</code>, повернеться помилка 403. Якщо цей параметр співпадає з заголовком <code>Origin</code> і вихід знаходиться у білому списку, буде встановлено заголовки <code>Access-Control-Allow-Origin</code> і <code>Access-Control-Allow-Credentials</code>.\n\nДля неавтентифікованих запитів укажіть значення <kbd>*</kbd>. Це дасть встановлення заголовка <code>Access-Control-Allow-Origin</code>, але <code>Access-Control-Allow-Credentials</code> буде <code>false</code> і всі дані про користувача будуть заборонені.",
        "apihelp-main-param-uselang": "Мова, що використовується для перекладу повідомлень. Список кодів можна видати на <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> з <kbd>siprop=languages</kbd> або вказати <kbd>user</kbd> на використання поточного налаштування мови користувача, або вказати <kbd>content</kbd> на використання мови вмісту цієї вікі.",
        "apihelp-main-param-errorformat": "Формат попереджень і тексту помилок.\n; plaintext: вікітекст із прираними HTML-тегами і заміненими HTML-мнемоніками.\n; wikitext: неопрацьований вікітекст.\n; html: HTML.\n; raw: лише ключ і параметри повідомлення.\n; none: без тексту, тільки коди помилок.\n; bc: формат, який використовувався до MediaWiki 1.29. <var>errorlang</var> і <var>errorsuselocal</var> ігноруються.",
+       "apihelp-main-param-errorlang": "Мова, яку використовувати для попереджень і помилок. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> із <kbd>siprop=languages</kbd> повертає список кодів мов, або ж вкажіть <kbd>content</kbd>, щоб використати мову вмісту поточної вікі, або вкажіть <kbd>uselang</kbd>, щоб використовувати те ж значення, що й параметр <var>uselang</var>.",
+       "apihelp-main-param-errorsuselocal": "Якщо задано, тексти помилок використовуватимуть локальні повідомлення з простору назв {{ns:MediaWiki}}.",
        "apihelp-block-description": "Заблокувати користувача.",
-       "apihelp-block-param-user": "Ім'я користувача, IP-адреса або діапазон IP-адрес для блокування.",
+       "apihelp-block-param-user": "Ім'я користувача, IP-адреса або діапазон IP-адрес для блокування. Не може бути використано разом із <var>$1userid</var>",
+       "apihelp-block-param-userid": "Ідентифікатор користувача, який заблокувати. Не може бути використано разом із <var>$1user</var>.",
        "apihelp-block-param-expiry": "Закінчення часу. Може бути відносним (напр., <kbd>5 місяців</kbd> або <kbd>2 тижні</kbd>) чи абсолютним (напр., <kbd>2014-09-18T12:34:56Z</kbd>). Якщо вказано <kbd>infinite</kbd>, <kbd>indefinite</kbd> або <kbd>never</kbd>, блокування не закінчиться ніколи.",
        "apihelp-block-param-reason": "Причина блокування.",
        "apihelp-block-param-anononly": "Блокувати тільки анонімних користувачів (тобто відключити можливість анонімних редагувань з цієї IP-адреси).",
        "apihelp-query+imageinfo-paramvalue-prop-archivename": "Додає назву файлу архівної версії для неостанніх версій.",
        "apihelp-query+imageinfo-paramvalue-prop-bitdepth": "Додає бітну глибину версії.",
        "apihelp-query+imageinfo-paramvalue-prop-uploadwarning": "Використовується на Special:Upload page для отримання інформації про наявний файл. Не призначено для використання поза ядром MediaWiki.",
+       "apihelp-query+imageinfo-paramvalue-prop-badfile": "Додає інформацію про те, чи перебуває файл у \n[[MediaWiki:Bad image list|списку недозволених файлів]]",
        "apihelp-query+imageinfo-param-limit": "Скільки виводити версій кожного файлу.",
        "apihelp-query+imageinfo-param-start": "Часова мітка, з якої почати список.",
        "apihelp-query+imageinfo-param-end": "Часова мітка, на якій закінчити список.",
        "apihelp-query+imageinfo-param-extmetadatamultilang": "Якщо переклади властивості extmetadata доступні, вибрати їх усі.",
        "apihelp-query+imageinfo-param-extmetadatafilter": "Якщо вказано і не порожньо, буде видано лише ці ключі для $1prop=extmetadata.",
        "apihelp-query+imageinfo-param-urlparam": "Рядок окремого параметра. Наприклад, PDF-ки можуть використовувати <kbd>page15-100px</kbd>. <var>$1urlwidth</var> повинно використовуватись і бути сумісним з <var>$1urlparam</var>.",
+       "apihelp-query+imageinfo-param-badfilecontexttitle": "Якщо встановлено <kbd>$2prop=badfile</kbd>, це — назва сторінки, що буде використана при аналізі [[MediaWiki:Bad image list]]",
        "apihelp-query+imageinfo-param-localonly": "Шукати лише файли у локальному репозиторії.",
        "apihelp-query+imageinfo-example-simple": "Вибрати інформацію про поточну версію [[:File:Albert Einstein Head.jpg]].",
        "apihelp-query+imageinfo-example-dated": "Вибрати інформацію про версії [[:File:Test.jpg]] від 2008 і раніше.",
        "apihelp-query+users-paramvalue-prop-cancreate": "Вказує, чи можна створити обліковий запис для допустимих, але незареєстрованих імен користувачів.",
        "apihelp-query+users-param-attachedwiki": "Із <kbd>$1prop=centralids</kbd>, вказати, чи користувач має приєднану вікі, визначену цим ідентифікатором.",
        "apihelp-query+users-param-users": "Список користувачів, для яких отримати інформацію.",
+       "apihelp-query+users-param-userids": "Список ідентифікаторів користувачів, щодо яких треба отримати інформацію.",
        "apihelp-query+users-param-token": "Використати натомість <kbd>[[Special:ApiHelp/query+tokens|action=query&meta=tokens]]</kbd>.",
        "apihelp-query+users-example-simple": "Вивести інформацію для користувача <kbd>Example</kbd>.",
        "apihelp-query+watchlist-description": "Отримати нещодавні зміни сторінок у списку спостереження поточного користувача.",
        "apihelp-tokens-example-edit": "Отримати жетон редагування (за замовчуванням).",
        "apihelp-tokens-example-emailmove": "Отримати жетон електронної пошти та жетон перейменування.",
        "apihelp-unblock-description": "Розблокувати користувача.",
-       "apihelp-unblock-param-id": "Ідентифікатор блоку чи розблокування (отриманий через <kbd>list=blocks</kbd>). Не може бути використано разом з <var>$1user</var>.",
-       "apihelp-unblock-param-user": "Ім'я користувача, IP-адреса чи IP-діапазон до розблокування. Не може бути використано разом з <var>$1id</var>.",
+       "apihelp-unblock-param-id": "Ідентифікатор блоку чи розблокування (отриманий через <kbd>list=blocks</kbd>). Не може бути використано разом із <var>$1user</var> або <var>$luserid</var>.",
+       "apihelp-unblock-param-user": "Ім'я користувача, IP-адреса чи IP-діапазон до розблокування. Не може бути використано разом із <var>$1id</var> або <var>$luserid</var>.",
+       "apihelp-unblock-param-userid": "Ідентифікатор користувача до розблокування. Не може бути використано разом із <var>$1id</var> або <var>$1user</var>.",
        "apihelp-unblock-param-reason": "Причина розблокування.",
        "apihelp-unblock-param-tags": "Змінити теги, що мають бути застосовані до запису в журналі блокувань.",
        "apihelp-unblock-example-id": "Зняти блокування з ідентифікатором #<kbd>105</kbd>.",
        "apihelp-userrights-param-reason": "Причина зміни.",
        "apihelp-userrights-example-user": "Додати користувача <kbd>FooBot</kbd> до групи <kbd>bot</kbd> та вилучити із груп <kbd>sysop</kbd> та <kbd>bureaucrat</kbd>.",
        "apihelp-userrights-example-userid": "Додати користувача з ідентифікатором <kbd>123</kbd> до групи <kbd>bot</kbd> та вилучити із груп <kbd>sysop</kbd> та <kbd>bureaucrat</kbd>.",
+       "apihelp-validatepassword-description": "Перевірити пароль на предмет відповідності політикам вікі щодо паролів.\n\nРезультати перевірки вказуються як <samp>Good</samp> якщо пароль прийнятний, <samp>Change</samp> якщо пароль може використовуватись для входу, але його треба змінити, і <samp>Invalid</samp> — якщо пароль використовувати не можна.",
+       "apihelp-validatepassword-param-password": "Пароль до перевірки.",
+       "apihelp-validatepassword-param-user": "Ім'я користувача, для використання при тестуванні створення облікового запису. Вказаний користувач не повинен існувати.",
+       "apihelp-validatepassword-param-email": "Адреса електронної пошти, для використання при тестуванні створення облікового запису.",
+       "apihelp-validatepassword-param-realname": "Справжнє ім'я, для використання при тестуванні створення облікового запису.",
+       "apihelp-validatepassword-example-1": "Перевірити пароль <kbd>foobar</kbd> для поточного користувача.",
+       "apihelp-validatepassword-example-2": "Перевірити пароль <kbd>qwerty</kbd> для створення користувача <kbd>Example</kbd>.",
        "apihelp-watch-description": "Додати або вилучити сторінки з списку спостереження поточного користувача.",
        "apihelp-watch-param-title": "Сторінки до додання/вилучення. Використовуйте <var>$1titles</var> натомість.",
        "apihelp-watch-param-unwatch": "Якщо вказано, сторінку буде вилучено зі списку спостереження замість додання до нього.",
        "api-help-authmanagerhelper-returnurl": "URL-адреса повернення для сторонніх автентифікаційних потоків повинна бути абсолютною. Обов'язковим є це, або <var>$1continue</var>. \n\nПри отриманні відповіді <samp>REDIRECT</samp>, найбільш звичною Вашою дією буде відкриття браузерного чи іншого веб-перегляду вказаного URL-посилання для стороннього потоку автентифікації. Коли ця операція буде завершена, стороння програма перенаправить веб-переглядач на цю URL-адресу. Ви повинні видобувати будь-які параметри запитів або POST-параметри із цієї URL-адреси, і передавати їх як запит <var>$1continue</var> до цього модуля API.",
        "api-help-authmanagerhelper-continue": "Цей запит є продовженням після попередньої відповіді <samp>UI</samp> або <samp>REDIRECT</samp>. Або це, або <var>$1returnurl</var> є обов'язковим.",
        "api-help-authmanagerhelper-additional-params": "Цей модуль приймає додаткові параметри, залежно від доступних автентифікаційних запитів. Використовуйте <kbd>[[Special:ApiHelp/query+authmanagerinfo|action=query&meta=authmanagerinfo]]</kbd> за допомогою <kbd>amirequestsfor=$1</kbd> (або попередню відповідь від цього модуля, якщо це застосовно), аби визначити доступні запити та поля, які вони використовують.",
+       "apierror-allimages-redirect": "Використовуйте <kbd>gaifilterredir=nonredirects</kbd> замість <var>redirects</var> при використанні <kbd>allimages</kbd> як генератора.",
+       "apierror-allpages-generator-redirects": "Використовуйте <kbd>gapfilterredir=nonredirects</kbd> замість <var>redirects</var> при використанні <kbd>allpages</kbd> як генератора.",
+       "apierror-appendnotsupported": "Не вдається додавати до сторінок, що використовують контентну модель $1.",
+       "apierror-articleexists": "Статтю, яку Ви намагались створити, вже було створено.",
+       "apierror-assertbotfailed": "Твердження, що користувач має право <code>bot</code>, виявилося хибним.",
+       "apierror-assertnameduserfailed": "Твердження, що ім'я користувача — «$1», виявилося хибним.",
+       "apierror-assertuserfailed": "Твердження, що користувач перебуває в системі, виявилося хибним.",
+       "apierror-autoblocked": "Вашу IP-адресу було автоматично заблоковано, оскільки її використовував заблокований користувач.",
+       "apierror-badconfig-resulttoosmall": "Значення <code>$wgAPIMaxResultSize</code> у цій вікі є надто малим, щоб містити базову інформацію щодо результатів.",
+       "apierror-badcontinue": "Параметр продовження недійсний. Вам треба вказати початкове значення, отримане з попереднього запиту.",
+       "apierror-baddiff": "Цю різницю версій неможливо відтворити: одна або й обидві версії не існують, або Ви не маєте прав на їх перегляд.",
+       "apierror-baddiffto": "Для <var>$1diffto</var> треба задати невід'ємне число,<kbd>prev</kbd>, <kbd>next</kbd> або <kbd>cur</kbd>.",
+       "apierror-badformat-generic": "Запитуваний формат $1 не підтримується контентною моделлю$2.",
+       "apierror-badformat": "Запитуваний формат $1 не підтримується контентною моделлю $2, що використовується $3.",
+       "apierror-badgenerator-notgenerator": "Модуль <kbd>$1</kbd> не може бути використаний як генератор.",
+       "apierror-badgenerator-unknown": "Невідомий <kbd>generator=$1</kbd>.",
+       "apierror-badip": "Параметр IP є недійсним.",
+       "apierror-badmd5": "Вказаний хеш MD5 був неправильним.",
+       "apierror-badmodule-badsubmodule": "Модуль <kbd>$1</kbd> не має підмодуля «$2».",
+       "apierror-badmodule-nosubmodules": "Модуль <kbd>$1</kbd> не має підмодулів.",
+       "apierror-badparameter": "Недійсне значення для параметра <var>$1</var>.",
+       "apierror-badquery": "Неприпустимий запит.",
+       "apierror-badtimestamp": "Недійсне значення «$2» для параметра мітки часу <var>$1</var>.",
+       "apierror-badtoken": "Недійсний токен CSRF.",
+       "apierror-badupload": "Параметр завантаження файлу <var>$1</var> не є завантаженням файлу; не забудьте використати <code>multipart/form-data</code> для Вашого POST і додайте назву файлу в шапку <code>Content-Disposition</code>.",
+       "apierror-badurl": "Недійсне значення «$2» для URL-параметра <var>$1</var>.",
+       "apierror-baduser": "Недійсне значення «$2» для параметра користувача <var>$1</var>.",
+       "apierror-badvalue-notmultivalue": "Відокремлення значень через U+001F може використовуватись лише в тих параметрах, де використання двох і більше значень є прийнятним.",
+       "apierror-bad-watchlist-token": "Надано некоректний токен списку спостереження. Будь ласка, подайте коректний токен на сторінці [[Special:Preferences|Спеціальна:Налаштування]].",
+       "apierror-blockedfrommail": "Вам заблоковано можливість надсилання електронної пошти.",
+       "apierror-blocked": "Вам заблоковано можливість редагування.",
+       "apierror-botsnotsupported": "Інтерфейс не підтримується для ботів.",
+       "apierror-cannotreauthenticate": "Ця діє недоступна, оскільки Вашу ідентичність неможливо перевірити.",
+       "apierror-cannotviewtitle": "Ви не маєте дозволу на перегляд $1.",
+       "apierror-cantblock-email": "Ви не маєте прав на блокування користувачам можливості надсилання електронної пошти через вікі.",
+       "apierror-cantblock": "Ви не маєте прав на блокування користувачів.",
+       "apierror-cantchangecontentmodel": "Ви не маєте прав на зміну контентної моделі сторінки.",
+       "apierror-canthide": "Ви не маєте прав на приховування імен користувачів у журналі блокувань.",
+       "apierror-cantimport-upload": "Ви не маєте прав на імпорт завантажених сторінок.",
+       "apierror-cantimport": "Ви не маєте прав на імпорт сторінок.",
+       "apierror-cantoverwrite-sharedfile": "Цільовий файл існує в загальному репозиторії, і Ви не маєте прав, щоб проігнорувати це.",
+       "apierror-cantsend": "Ви не увійшли в систему, не маєте підтвердженої електронної адреси, або не маєте дозволу на надсилання електронної пошти іншим користувачам, тож Ви не можете надсилати електронну пошту.",
+       "apierror-cantundelete": "Не вдалося відновити: запитувані версії або не існують, або їх вже було відновлено.",
+       "apierror-changeauth-norequest": "Не вдалося створити запит на зміну.",
+       "apierror-chunk-too-small": "Мінімальний розмір шматка становить $1 {{PLURAL:$1|байт|байти|байтів}} для некінцевих шматків.",
+       "apierror-cidrtoobroad": "$1 CIDR-діапазони, ширші ніж /$2, недозволені.",
+       "apierror-compare-inputneeded": "Назва, ідентифікатор сторінки, або номер версії потрібні як для параметра <var>from</var>, так і для <var>to</var>.",
+       "apierror-contentserializationexception": "Невдача серіалізації вмісту: $1",
+       "apierror-contenttoobig": "Наданий Вами вміст перевищує ліміт у $1 {{PLURAL:$1|кілобайт|кілобайти|кілобайтів}} розміру сторінки.",
+       "apierror-copyuploadbaddomain": "Завантаження за URL-адресою недозволені з цього домену.",
+       "apierror-copyuploadbadurl": "Завантаження з цієї URL-адреси недозволені.",
+       "apierror-create-titleexists": "Наявні назви не можна захистити за допомогою <kbd>create</kbd>.",
+       "apierror-csp-report": "Помилка при опрацюванні CSP-звіту: $1.",
+       "apierror-databaseerror": "[$1] Помилка запиту до бази даних.",
+       "apierror-deletedrevs-param-not-1-2": "Параметр <var>$1</var> не може використовуватись у режимах 1 або 2.",
+       "apierror-deletedrevs-param-not-3": "Параметр <var>$1</var> не може використовуватись у режимі 3.",
+       "apierror-emptynewsection": "Створення нових порожніх розділів неможливе.",
+       "apierror-emptypage": "Створення нових порожніх сторінок недозволене.",
+       "apierror-exceptioncaught": "[$1] Виявлено виняток: $2",
+       "apierror-filedoesnotexist": "Файл не існує.",
+       "apierror-fileexists-sharedrepo-perm": "Цільовий файл існує у загальному репозиторії. Використовуйте параметр <var>ignorewarnings</var>, щоб проігнорувати це.",
+       "apierror-filenopath": "Не вдалося отримати шлях до локального файлу.",
+       "apierror-filetypecannotberotated": "Тип файлу не можна повернути.",
+       "apierror-formatphp": "Цю відповідь не можна представити через <kbd>format=php</kbd>. Див. https://phabricator.wikimedia.org/T68776.",
+       "apierror-imageusage-badtitle": "Назва для <kbd>$1</kbd> має бути файлом.",
+       "apierror-import-unknownerror": "Невідома помилка при імпорті: $1.",
+       "apierror-integeroutofrange-abovebotmax": "<var>$1</var> не може мати значення понад $2 (встановлено як $3) для ботів чи адмінів.",
+       "apierror-integeroutofrange-abovemax": "<var>$1</var> не може мати значення понад $2 (встановлено як $3) для користувачів.",
+       "apierror-integeroutofrange-belowminimum": "<var>$1</var> не може мати значення менш як $2 (встановлено як $3).",
+       "apierror-invalidcategory": "Введена Вами назва категорії недійсна.",
+       "apierror-invalid-chunk": "Зміщення плюс поточний шматок мають більший розмір, аніж заявлений розмір файлу.",
+       "apierror-invalidexpiry": "Недійсний час завершення «$1».",
+       "apierror-invalid-file-key": "Недійсний ключ файлу.",
+       "apierror-invalidlang": "Недійсний код мови для параметра <var>$1</var>.",
+       "apierror-invalidoldimage": "Параметр «oldimage» має недійсний формат.",
+       "apierror-invalidparammix-cannotusewith": "Параметр <kbd>$1</kbd> не можна використовувати з <kbd>$2</kbd>.",
+       "apierror-invalidparammix-mustusewith": "Параметр <kbd>$1</kbd> можна використовувати тільки з  <kbd>$2</kbd>.",
+       "apierror-invalidparammix-parse-new-section": "<kbd>section=new</kbd> не можна поєднувати з параметрами <var>oldid</var>, <var>pageid</var> чи <var>page</var>. Будь ласка, використовуйте <var>title</var> і <var>text</var>.",
+       "apierror-invalidparammix": "{{PLURAL:$2|Ці параметри}} $1 не можна використовувати водночас.",
+       "apierror-invalidsection": "Параметр «section» має бути дійсним ідентифікатором розділу або <kbd>new</kbd>.",
+       "apierror-invalidsha1base36hash": "Поданий хеш SHA1Base36 недійсний.",
+       "apierror-invalidsha1hash": "Поданий хеш SHA1 недійсний.",
+       "apierror-invalidtitle": "Погана назва «$1».",
+       "apierror-invalidurlparam": "Недійсне значення для <var>$1urlparam</var> (<kbd>$2=$3</kbd>).",
+       "apierror-invaliduser": "Недійсне ім'я користувача «$1».",
+       "apierror-maxlag-generic": "Очікування на сервер бази даних: затримка $1 {{PLURAL:$1|секунда|секунди|секунд}}.",
+       "apierror-maxlag": "Очікування на $2: затримка $1 {{PLURAL:$1|секунда|секунди|секунд}}.",
+       "apierror-mimesearchdisabled": "MIME-пошук вимкнений у скупому режимі.",
+       "apierror-missingcontent-pageid": "Відсутній вміст для сторінки з ідентифікатором $1.",
+       "apierror-missingparam-at-least-one-of": "{{PLURAL:$2|Параметр|Щонайменше один параметрів}} $1 є обов'язковим.",
+       "apierror-missingparam-one-of": "{{PLURAL:$2|Параметр|Один з параметрів}} $1 є обов'язковим.",
+       "apierror-missingparam": "Параметр <var>$1</var> має бути заповнений.",
+       "apierror-missingrev-pageid": "Немає поточної версії сторінки з ідентифікатором $1.",
+       "apierror-missingtitle-createonly": "Відсутні назви можна захистити тільки через <kbd>create</kbd>.",
+       "apierror-missingtitle": "Вказана Вами сторінка не існує.",
+       "apierror-missingtitle-byname": "Сторінка $1 не існує.",
+       "apierror-moduledisabled": "Модуль <kbd>$1</kbd> було вимкнено.",
+       "apierror-multival-only-one-of": "{{PLURAL:$3|Лише значення|Лише одне значення з}} $2 дозволене для параметра <var>$1</var>.",
+       "apierror-multival-only-one": "Лише одне значення дозволене для параметра <var>$1</var>.",
+       "apierror-multpages": "<var>$1</var> може використовуватись тільки з однією сторінкою.",
+       "apierror-mustbeloggedin-changeauth": "Вам треба увійти в систему, щоб змінити автентифікаційні дані.",
+       "apierror-mustbeloggedin-generic": "Ви повинні перебувати в системі.",
+       "apierror-mustbeloggedin-linkaccounts": "Щоб зв'язувати облікові записи Вам треба увійти в систему.",
+       "apierror-mustbeloggedin-removeauth": "Щоб вилучати автентифікаційні дані Вам треба увійти в систему.",
+       "apierror-mustbeloggedin-uploadstash": "Сховок завантажень доступний тільки для зареєстрованих користувачів.",
+       "apierror-mustbeloggedin": "Для $1 Вам треба увійти в систему.",
+       "apierror-mustbeposted": "Модуль <kbd>$1</kbd> потребує запиту POST.",
+       "apierror-mustpostparams": "{{PLURAL:$2|Вказаний параметр було знайдено в рядку запиту, але має|Вказані параметри було знайдено в рядку запиту, але мають}} бути у тілі POST: $1.",
+       "apierror-noapiwrite": "Редагування цієї вікі через API вимкнено. Упевніться, що твердження <code>$wgEnableWriteAPI=true;</code> включено у файл <code>LocalSettings.php</code> цієї вікі.",
+       "apierror-nochanges": "На жодні зміни запиту не було.",
+       "apierror-nodeleteablefile": "Немає такої старої версії файлу.",
+       "apierror-no-direct-editing": "Пряме редагування через API не підтримується контентною моделлю $1, що використовується $2.",
+       "apierror-noedit-anon": "Анонімні користувачі не можуть редагувати сторінки.",
+       "apierror-noedit": "У Вас немає прав на редагування сторінок.",
+       "apierror-noimageredirect-anon": "Анонімні користувачі не можуть створювати перенаправлення на файли.",
+       "apierror-noimageredirect": "Ви не маєте прав на створення перенаправлень на файли.",
+       "apierror-nosuchlogid": "Немає журнального запису з ідентифікатором $1.",
+       "apierror-nosuchpageid": "Немає сторінки з ідентифікатором $1.",
+       "apierror-nosuchrcid": "Немає недавньої зміни з ідентифікатором $1.",
+       "apierror-nosuchrevid": "Немає версії з ідентифікатором $1.",
+       "apierror-nosuchsection": "Немає розділу $1.",
+       "apierror-nosuchsection-what": "Немає розділу $1 на сторінці $2.",
+       "apierror-nosuchuserid": "Немає користувача з ідентифікатором $1.",
+       "apierror-notarget": "Ви не вказали дійсної цілі для цієї дії.",
+       "apierror-notpatrollable": "Версія r$1 не може бути відпатрульована, оскільки вона надто стара.",
+       "apierror-nouploadmodule": "Не встановлено модуля завантаження.",
+       "apierror-opensearch-json-warnings": "Попередження не можуть бути представлені у форматі OpenSearch JSON.",
+       "apierror-pagecannotexist": "Простір назв не дозволяє фактичних сторінок.",
+       "apierror-pagedeleted": "Цю сторінку було вилучено після того, як Ви отримали її мітку часу.",
+       "apierror-paramempty": "Параметр <var>$1</var> не може бути порожнім.",
+       "apierror-parsetree-notwikitext": "<kbd>prop=parsetree</kbd> підтримується лише для вмісту у форматі вікірозмітки.",
+       "apierror-parsetree-notwikitext-title": "<kbd>prop=parsetree</kbd> підтримується лише для вмісту у форматі вікірозмітки. $1 використовує контентну модель $2.",
+       "apierror-pastexpiry": "Час закінчення «$1» — в минулому.",
+       "apierror-permissiondenied": "Ви не маєте прав на $1.",
+       "apierror-permissiondenied-generic": "Доступ заборонено.",
+       "apierror-permissiondenied-patrolflag": "Вам потрібне право <code>patrol</code> або <code>patrolmarks</code>, щоб подати запит на прапорець «відпатрульовано».",
+       "apierror-permissiondenied-unblock": "Ви не маєте прав на розблокування користувачів.",
+       "apierror-prefixsearchdisabled": "Пошук за префіксом вимкнено у скупому режимі.",
+       "apierror-promised-nonwrite-api": "HTTP-заголовок <code>Promise-Non-Write-API-Action</code> не можна надсилати до модулів API із режимом запису.",
+       "apierror-protect-invalidaction": "Недійсний тип захисту «$1».",
+       "apierror-protect-invalidlevel": "Недійсний рівень захисту «$1».",
+       "apierror-ratelimited": "Ви перевищили свій ліміт частоти. Будь ласка, почекайте деякий час і спробуйте знову.",
+       "apierror-readapidenied": "Вам потрібне право на читання, щоб використовувати цей модуль.",
+       "apierror-readonly": "Ця вікі наразі перебуває в режимі тільки для читання.",
+       "apierror-reauthenticate": "Ви останнім часом не проходили автентифікацію в цій сесії. Будь ласка, пройдіть автентифікацію ще раз.",
+       "apierror-redirect-appendonly": "Ви зробили спробу редагування з використанням режиму переходу за перенаправленням, який має використовуватись разом із <kbd>section=new</kbd>, <var>prependtext</var>, або <var>appendtext</var>.",
+       "apierror-revdel-mutuallyexclusive": "Одне й те ж поле не може використовуватись у <var>hide</var> і <var>show</var> водночас.",
+       "apierror-revdel-needtarget": "Для цього типу RevDel необхідна цільова назва.",
+       "apierror-revdel-paramneeded": "Щонайменше одне значення необхідне для <var>hide</var> та/або <var>show</var>.",
+       "apierror-revisions-norevids": "Параметр <var>revids</var> не можна використовувати з опціями списку (<var>$1limit</var>, <var>$1startid</var>, <var>$1endid</var>, <kbd>$1dir=newer</kbd>, <var>$1user</var>, <var>$1excludeuser</var>, <var>$1start</var>, і <var>$1end</var>).",
+       "apierror-revisions-singlepage": "Було використано <var>titles</var>, <var>pageids</var> або генератор для постачання декількох сторінок, але параметри <var>$1limit</var>, <var>$1startid</var>, <var>$1endid</var>, <kbd>$1dir=newer</kbd>, <var>$1user</var>, <var>$1excludeuser</var>, <var>$1start</var>, і <var>$1end</var> можуть використовуватися тільки на одній сторінці.",
+       "apierror-revwrongpage": "r$1 не є версією сторінки $2.",
+       "apierror-searchdisabled": "<var>$1</var> пошук вимкнено.",
+       "apierror-sectionreplacefailed": "Не вдалося об'єднати оновлений розділ.",
+       "apierror-sectionsnotsupported": "Розділи не підтримуються для контентної моделі $1.",
+       "apierror-sectionsnotsupported-what": "Розділи не підтримуються $1.",
+       "apierror-show": "Неправильний параметр — не можна надавати взаємовиключні значення.",
+       "apierror-siteinfo-includealldenied": "Не можна переглядати інформацію щодо всіх серверів, якщо тільки <var>$wgShowHostNames</var> не вказано як «true».",
+       "apierror-sizediffdisabled": "Різниця у розмірах вимкнена в скупому режимі.",
+       "apierror-spamdetected": "Ваше редагування було відхилено, оскільки воно містило фрагмент спаму: <code>$1</code>.",
+       "apierror-specialpage-cantexecute": "Ви не маєте прав на перегляд результатів цієї спеціальної сторінки.",
+       "apierror-stashedfilenotfound": "Не вдалося знайти файл у сховку: $1.",
+       "apierror-stashedit-missingtext": "У сховку не знайдено збереженого тексту із заданим хешем.",
+       "apierror-stashfailed-complete": "Завантаження по шматках вже завершилося, перегляньте статус, щоб дізнатися подробиці.",
+       "apierror-stashfailed-nosession": "Немає сесії завантажень по шматках із цим ключем.",
+       "apierror-stashfilestorage": "Не вдалося зберегти завантаження у сховку: $1",
+       "apierror-stashinvalidfile": "Недійсний файл у сховку.",
+       "apierror-stashnosuchfilekey": "Немає такого filekey: $1.",
+       "apierror-stashpathinvalid": "Ключ файлу має неправильний формат або є недійсним з іншої причини: $1.",
+       "apierror-stashwrongowner": "Неправильний власник: $1",
+       "apierror-stashzerolength": "Довжина файлу дорівнює нулю, і його не можна зберегти у сховку: $1.",
+       "apierror-systemblocked": "Вас автоматично заблоковано MediaWiki.",
+       "apierror-templateexpansion-notwikitext": "Розширення шаблонів підтримується лише для вмісту у форматі вікірозмітки. $1 використовує контентну модель $2.",
+       "apierror-toofewexpiries": "$1 {{PLURAL:$1|мітка часу завершення була надана|мітки часу завершення були надані|міток часу завершення було надано}}, тоді як {{PLURAL:$2|потрібна була $2 така мітка|потрібні були $2 таких мітки|потрібно було $2 таких міток}}.",
+       "apierror-unknownaction": "Вказана дія, <kbd>$1</kbd>, нерозпізнана.",
+       "apierror-unknownerror-editpage": "Невідома помилка EditPage: $1.",
+       "apierror-unknownerror-nocode": "Невідома помилка.",
+       "apierror-unknownerror": "Невідома помилка: «$1».",
+       "apierror-unknownformat": "Невідомий формат «$1».",
+       "apierror-unrecognizedparams": "{{PLURAL:$2|Нерозпізнаний параметр|Нерозпізнані параметри}}: $1.",
+       "apierror-unrecognizedvalue": "Нерозпізнане значення для параметра <var>$1</var>: $2.",
+       "apierror-unsupportedrepo": "Місцевий репозиторій файлів не підтримує запитів щодо всіх зображень.",
+       "apierror-upload-filekeyneeded": "Треба вказати <var>filekey</var>, коли <var>offset</var> є ненульовим.",
+       "apierror-upload-filekeynotallowed": "Не можна вказувати <var>filekey</var>, коли <var>offset</var> дорівнює 0.",
+       "apierror-upload-inprogress": "Завантаження зі сховку вже в процесі.",
+       "apierror-upload-missingresult": "Немає результатів у даних статусу.",
+       "apierror-urlparamnormal": "Не вдалося нормалізувати параметри зображення для $1.",
+       "apierror-writeapidenied": "Ви не маєте дозволу на редагування цієї вікі через API.",
+       "apiwarn-alldeletedrevisions-performance": "Для підвищення продуктивності при генеруванні назв, встановіть <kbd>$1dir=newer</kbd>.",
+       "apiwarn-badurlparam": "Не вдалося парсити <var>$1urlparam</var> для $2. Використовується лише ширина і висота.",
+       "apiwarn-badutf8": "Значення, вказане для <var>$1</var>, містить недійсні або ненормалізовані дані. Текстові дані мають бути дійсними, NFC-нормалізований Unicode без контрольних символів C0, окрім HT (\\t), LF (\\n), і CR (\\r).",
+       "apiwarn-checktoken-percentencoding": "Перевірте, чи символи, такі як «+» у токені, пройшли правильне процентне кодування в URL.",
+       "apiwarn-deprecation-deletedrevs": "<kbd>list=deletedrevs</kbd> є застарілим. Будь ласка, використовуйте замість нього <kbd>prop=deletedrevisions</kbd> або <kbd>list=alldeletedrevisions</kbd>.",
+       "apiwarn-deprecation-expandtemplates-prop": "Оскільки не задано жодних значень для параметра <var>prop</var>, як вихідні дані було використано старий формат. Цей формат є застарілим, і в майбутньому параметру <var>prop</var> буде задано стандартне значення, наслідком чого стане те, що завжди використовуватиметься новий формат.",
+       "apiwarn-deprecation-httpsexpected": "Використано HTTP, тоді як очікувалося використання HTTPS.",
+       "apiwarn-deprecation-login-botpw": "Вхід в основний обліковий запис через <kbd>action=login</kbd> є застарілим, і може припинити працювати, без попередження. Щоб продовжити вхід у систему через <kbd>action=login</kbd>, див. [[Special:BotPasswords]]. Щоб безпечно продовжити, використовуючи вхід в основний обліковий запис, див. <kbd>action=clientlogin</kbd>.",
+       "apiwarn-deprecation-login-nobotpw": "Вхід в основний обліковий запис через <kbd>action=login</kbd> є застарілим, і може припинити працювати, без попередження. Щоб безпечно увійти в систему, див. <kbd>action=clientlogin</kbd>.",
+       "apiwarn-deprecation-login-token": "Отримання токена через <kbd>action=login</kbd> є застарілим. Використовуйте натомість <kbd>action=query&meta=tokens&type=login</kbd>.",
+       "apiwarn-deprecation-parameter": "Параметр <var>$1</var> — застарілий.",
+       "apiwarn-deprecation-parse-headitems": "<kbd>prop=headitems</kbd> є застарілим, починаючи з MediaWiki 1.28. Використовуйте <kbd>prop=headhtml</kbd> при створенні нових документів HTML, або <kbd>prop=modules|jsconfigvars</kbd> при оновленні документа з боку клієнта.",
+       "apiwarn-deprecation-purge-get": "Використання <kbd>action=purge</kbd> через GET є застарілим. Використовуйте POST замість цього.",
+       "apiwarn-deprecation-withreplacement": "<kbd>$1</kbd> є застарілим. Будь ласка, використовуйте натомість <kbd>$2</kbd>.",
+       "apiwarn-difftohidden": "Не вдалося відкрити версію r$1: вміст приховано.",
+       "apiwarn-errorprinterfailed": "Невдача через помилку принтера. Буде здійснено повторну спробу без параметрів.",
+       "apiwarn-errorprinterfailed-ex": "Невдача через помилку принтера (буде здійснено повторну спробу без параметрів): $1",
+       "apiwarn-invalidcategory": "«$1» не є категорією.",
+       "apiwarn-invalidtitle": "«$1» не є коректною назвою.",
+       "apiwarn-invalidxmlstylesheetext": "Таблиця стилів повинна мати розширення <code>.xsl</code>.",
+       "apiwarn-invalidxmlstylesheet": "Вказана таблиця стилів є недійсною або не існує.",
+       "apiwarn-invalidxmlstylesheetns": "Таблиця стилів має перебувати в просторі назв {{ns:MediaWiki}}.",
+       "apiwarn-moduleswithoutvars": "Задано властивість <kbd>modules</kbd>, але не задано <kbd>jsconfigvars</kbd> або <kbd>encodedjsconfigvars</kbd>. Змінні конфігурації необхідні для коректного використання модуля.",
+       "apiwarn-notfile": "«$1» не є файлом.",
+       "apiwarn-nothumb-noimagehandler": "Не вдалося створити мініатюру, оскільки $1 не має пов'язаного обробника зображень.",
+       "apiwarn-parse-nocontentmodel": "Не задано <var>title</var> або <var>contentmodel</var>, буде використано $1.",
+       "apiwarn-parse-titlewithouttext": "<var>title</var> використано без <var>text</var>, і надіслано запит на оброблені властивості сторінки. Може \nВи хотіли використати <var>page</var> замість <var>title</var>?",
+       "apiwarn-redirectsandrevids": "Вирішення перенаправлень не може використовуватись разом з параметром <var>revids</var>. Усі перенаправлення, на які вказує <var>revids</var>, не було вирішено.",
+       "apiwarn-tokennotallowed": "Дія «$1» недозволена для поточного користувача.",
+       "apiwarn-tokens-origin": "Токени не можна отримати, поки не застосована політика одного походження.",
+       "apiwarn-toomanyvalues": "Надто багато значень задано для параметра <var>$1</var>: ліміт становить $2.",
+       "apiwarn-truncatedresult": "Цей результат було скорочено, оскільки інакше він перевищив би ліміт у $1 байтів.",
+       "apiwarn-unclearnowtimestamp": "Вказування «$2» для параметра мітки часу <var>$1</var> є застарілим. Якщо з якоїсь причини Вам треба чітко вказати поточний час без вираховування його з боку клієнта, використайте <kbd>now<kbd>.",
+       "apiwarn-unrecognizedvalues": "{{PLURAL:$3|Нерозпізнане|Нерозпізнані}} значення для параметра <var>$1</var>: $2.",
+       "apiwarn-unsupportedarray": "Параметр <var>$1</var> використовує непідтримуваний синтаксис PHP-масиву.",
+       "apiwarn-urlparamwidth": "Ігнорування значення ширини, встановленого в <var>$1urlparam</var> ($2) на користь значення ширини, запозиченого із <var>$1urlwidth</var>/<var>$1urlheight</var> ($3).",
+       "apiwarn-validationfailed-badchars": "недійсні символи у ключі (лише <code>a-z</code>, <code>A-Z</code>, <code>0-9</code>, <code>_</code>, і <code>-</code> дозволені).",
+       "apiwarn-validationfailed-badpref": "недійсне налаштування.",
+       "apiwarn-validationfailed-cannotset": "не може бути встановлено цим модулем.",
+       "apiwarn-validationfailed-keytoolong": "ключ надто довгий (дозволено не більш як $1 байтів).",
+       "apiwarn-validationfailed": "Помилка перевірки для <kbd>$1</kbd>: $2",
+       "apiwarn-wgDebugAPI": "<strong>Попередження щодо безпеки</strong>: увімкнено <var>$wgDebugAPI</var>.",
+       "api-feed-error-title": "Помилка ($1)",
+       "api-usage-docref": "Див. $1 щодо використання API.",
+       "api-exception-trace": "$1 у $2($3)\n$4",
        "api-credits-header": "Автор(и)",
        "api-credits": "Розробники API:\n* Roan Kattouw (головний розробник вер. 2007–2009)\n* Victor Vasiliev\n* Bryan Tong Minh\n* Sam Reed\n* Yuri Astrakhan (творець, головний розробник вер. 2006 – вер. 2007)\n* Brad Jorsch (головний розробник 2013 – тепер)\n\nБудь ласка, надсилайте свої коментарі, пропозиції та запитання на mediawiki-api@lists.wikimedia.org\nабо зафайліть звіт про баґ на https://phabricator.wikimedia.org/."
 }
index 1692a6e..215f78b 100644 (file)
@@ -43,7 +43,8 @@
        "apihelp-main-param-errorlang": "用于警告和错误的语言。<kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd>带<kbd>siprop=languages</kbd>返回语言代码的列表,或指定<kbd>content</kbd>以使用此wiki的内容语言,或指定<kbd>uselang</kbd>以使用与<var>uselang</var>参数相同的值。",
        "apihelp-main-param-errorsuselocal": "如果指定,错误文本将使用来自{{ns:MediaWiki}}名字空间的本地自定义消息。",
        "apihelp-block-description": "封禁一位用户。",
-       "apihelp-block-param-user": "您要封禁的用户、IP地址或IP地址段。",
+       "apihelp-block-param-user": "要封禁的用户、IP地址或IP地址段。不能与<var>$1userid</var>一起使用",
+       "apihelp-block-param-userid": "要封禁的用户ID。不能与<var>$1user</var>一起使用。",
        "apihelp-block-param-expiry": "到期时间。可以是相对时间(例如<kbd>5 months</kbd>或<kbd>2 weeks</kbd>)或绝对时间(例如<kbd>2014-09-18T12:34:56Z</kbd>)。如果设置为<kbd>infinite</kbd>、<kbd>indefinite</kbd>或<kbd>never</kbd>,封禁将无限期。",
        "apihelp-block-param-reason": "封禁的原因。",
        "apihelp-block-param-anononly": "只封禁匿名用户(也就是说禁止此 IP 地址的匿名编辑)。",
        "apihelp-query+imageinfo-paramvalue-prop-archivename": "添加用于非最新修订的存档修订的文件名。",
        "apihelp-query+imageinfo-paramvalue-prop-bitdepth": "添加修订的字节深度。",
        "apihelp-query+imageinfo-paramvalue-prop-uploadwarning": "由Special:Upload所使用,以获取关于现有文件的信息。不适用于MediaWiki核心以外代码。",
+       "apihelp-query+imageinfo-paramvalue-prop-badfile": "无论文件是否在[[MediaWiki:Bad image list]]都添加",
        "apihelp-query+imageinfo-param-limit": "每个文件返回多少文件修订。",
        "apihelp-query+imageinfo-param-start": "开始列举的时间戳。",
        "apihelp-query+imageinfo-param-end": "列举的结束时间戳。",
        "apihelp-query+imageinfo-param-extmetadatamultilang": "如果用于extmetadata属性的翻译可用,则全部取得。",
        "apihelp-query+imageinfo-param-extmetadatafilter": "如果指定且非空,则只为$1prop=extmetadata返回这些键。",
        "apihelp-query+imageinfo-param-urlparam": "处理器特定的参数字符串。例如PDF可能使用<kbd>page15-100px</kbd>。<var>$1urlwidth</var>必须被使用,并与<var>$1urlparam</var>一致。",
+       "apihelp-query+imageinfo-param-badfilecontexttitle": "如果<kbd>$2prop=badfile</kbd>被设置,这会是在评估[[MediaWiki:Bad image list]]时使用的页面标题",
        "apihelp-query+imageinfo-param-localonly": "只看本地存储库的文件。",
        "apihelp-query+imageinfo-example-simple": "取得有关[[:File:Albert Einstein Head.jpg]]的当前版本的信息。",
        "apihelp-query+imageinfo-example-dated": "取得有关[[:File:Test.jpg]]自2008年以来版本的信息。",
        "apihelp-tokens-example-edit": "检索一个编辑令牌(默认)。",
        "apihelp-tokens-example-emailmove": "检索一个电子邮件令牌和一个移动令牌。",
        "apihelp-unblock-description": "解封一位用户。",
-       "apihelp-unblock-param-id": "解封时需要的封禁ID(通过<kbd>list=blocks</kbd>获得)。不能与<var>$1user</var>一起使用。",
-       "apihelp-unblock-param-user": "要解封的用户名、IP地址或IP段。不能与<var>$1id</var>一起使用。",
+       "apihelp-unblock-param-id": "解封时需要的封禁ID(通过<kbd>list=blocks</kbd>获得)。不能与<var>$1user</var>或<var>$luserid</var>一起使用。",
+       "apihelp-unblock-param-user": "要解封的用户名、IP地址或IP地址段。不能与<var>$1id</var>或<var>$luserid</var>一起使用。",
+       "apihelp-unblock-param-userid": "要封禁的用户ID。不能与<var>$1id</var>或<var>$1user</var>一起使用。",
        "apihelp-unblock-param-reason": "解封的原因。",
        "apihelp-unblock-param-tags": "要在封禁日志中应用到实体的更改标签。",
        "apihelp-unblock-example-id": "解封封禁ID #<kbd>105</kbd>。",
        "apierror-badurl": "用于URL参数<var>$1</var>的值“$2”无效。",
        "apierror-baduser": "用于用户参数<var>$1</var>的值“$2”无效。",
        "apierror-badvalue-notmultivalue": "U+001F多值分隔符只可以用于多值参数。",
+       "apierror-bad-watchlist-token": "提供了不正确的监视列表令牌。请在[[Special:Preferences]]设置正确的令牌。",
        "apierror-blockedfrommail": "您已被封禁,不能发送电子邮件。",
        "apierror-blocked": "您已被封禁,不能编辑。",
        "apierror-botsnotsupported": "此界面不支持机器人。",
+       "apierror-cannotreauthenticate": "由于您的身份不能被验证,此操作不可用。",
        "apierror-cannotviewtitle": "您不被允许查看$1。",
        "apierror-cantblock-email": "您没有权限封禁用户通过wiki发送电子邮件。",
        "apierror-cantblock": "您没有权限封禁用户。",
        "apierror-canthide": "您没有权限从封禁日志中隐藏用户名。",
        "apierror-cantimport-upload": "您没有权限导入上传的页面。",
        "apierror-cantimport": "您没有权限导入页面。",
+       "apierror-cantoverwrite-sharedfile": "目标文件存在于分享存储库,并且您没有权限覆盖它。",
        "apierror-cantsend": "您没有登录,您没有已确认的电子邮件地址,或者您未被允许向其他用户发送电子邮件,所以您不能发送电子邮件。",
+       "apierror-cantundelete": "不能还原:请求的修订版本可能不存在,或可能已被还原。",
        "apierror-changeauth-norequest": "创建更改请求失败。",
+       "apierror-chunk-too-small": "对于非最终块,最小块大小为$1{{PLURAL:$1|字节}}。",
        "apierror-cidrtoobroad": "比/$2更宽的$1 CIDR地址段不被接受。",
+       "apierror-compare-inputneeded": "需要标题、页面ID或修订版本号以用于<var>from</var>和<var>to</var>参数。",
        "apierror-contentserializationexception": "内容序列化失败:$1",
        "apierror-contenttoobig": "您提供的内容超过了$1{{PLURAL:$1|千字节}}的条目大小限制。",
        "apierror-copyuploadbaddomain": "不允许从此域名通过URL上传。",
        "apierror-emptypage": "不允许创建新的,空白的页面。",
        "apierror-exceptioncaught": "[$1]捕获异常:$2",
        "apierror-filedoesnotexist": "文件不存在。",
+       "apierror-fileexists-sharedrepo-perm": "目标文件存在于共享存储库。使用<var>ignorewarnings</var>参数覆盖它。",
        "apierror-filenopath": "不能获取本地文件路径。",
        "apierror-filetypecannotberotated": "文件类型不能旋转。",
        "apierror-formatphp": "此响应不能使用<kbd>format=php</kbd>代表。请参见https://phabricator.wikimedia.org/T68776。",
        "apierror-invalidoldimage": "旧图片参数有无效格式。",
        "apierror-invalidparammix-cannotusewith": "<kbd>$1</kbd>参数不能与<kbd>$2</kbd>一起使用。",
        "apierror-invalidparammix-mustusewith": "<kbd>$1</kbd>参数只能与<kbd>$2</kbd>一起使用。",
+       "apierror-invalidparammix-parse-new-section": "<kbd>section=new</kbd>不能连同<var>oldid</var>、<var>pageid</var>或<var>page</var>参数使用。请使用<var>title</var>和<var>text</var>。",
        "apierror-invalidparammix": "{{PLURAL:$2|参数}}$1不能一起使用。",
        "apierror-invalidsection": "章节参数必须为有效的章节ID或<kbd>new</kbd>。",
        "apierror-invalidsha1base36hash": "提供的SHA1Base36哈希无效。",
        "apierror-noapiwrite": "通过API编辑此wiki已禁用。请确保<code>$wgEnableWriteAPI=true;</code>声明包含在wiki的<code>LocalSettings.php</code>文件中。",
        "apierror-nochanges": "没有请求的更改。",
        "apierror-nodeleteablefile": "没有该文件的旧版本。",
+       "apierror-no-direct-editing": "$2使用的内容模型$1不支持通过API直接编辑。",
        "apierror-noedit-anon": "匿名用户不能编辑页面。",
        "apierror-noedit": "您没有权限编辑页面。",
        "apierror-noimageredirect-anon": "匿名用户不能创建图片重定向。",
        "apierror-nosuchrevid": "没有ID为$1的修订版本。",
        "apierror-nosuchsection": "没有章节$1。",
        "apierror-nosuchsection-what": "在$2中没有章节$1。",
+       "apierror-nosuchuserid": "没有ID为$1的用户。",
+       "apierror-notarget": "您没有为此章节指定有效目标。",
        "apierror-notpatrollable": "修订版本r$1不能巡查,因为它太旧了。",
        "apierror-nouploadmodule": "未设置上传模块。",
        "apierror-opensearch-json-warnings": "警告不能以OpenSearch JSON格式表示。",
        "apierror-revdel-mutuallyexclusive": "同一字段不能同时用于<var>hide</var>和<var>show</var>。",
        "apierror-revdel-needtarget": "此修订版本删除类型需要目标标题。",
        "apierror-revdel-paramneeded": "需要<var>hide</var>和/或<var>show</var>的至少一个值。",
+       "apierror-revisions-norevids": "<var>revids</var>参数不能与列表选项(<var>$1limit</var>、<var>$1startid</var>、<var>$1endid</var>、<kbd>$1dir=newer</kbd>、<var>$1user</var>、<var>$1excludeuser</var>、<var>$1start</var>和<var>$1end</var>)一起使用",
        "apierror-revisions-singlepage": "<var>titles</var>、<var>pageids</var>或发生器用于提供多个页面,但<var>$1limit</var>、<var>$1startid</var>、<var>$1endid</var>、<kbd>$1dir=newer</kbd>、<var>$1user</var>、<var>$1excludeuser</var>、<var>$1start</var>和<var>$1end</var>参数只能在一个页面上使用。",
        "apierror-revwrongpage": "r$1不是$2的修订版本。",
        "apierror-searchdisabled": "<var>$1</var>搜索已禁用。",
        "apierror-sectionreplacefailed": "不能合并更新的章节。",
        "apierror-sectionsnotsupported": "内容模型$1不支持章节。",
        "apierror-sectionsnotsupported-what": "章节不被$1所支持。",
+       "apierror-siteinfo-includealldenied": "除非<var>$wgShowHostNames</var>为真,否则不能查看所有服务器的信息。",
        "apierror-sizediffdisabled": "大小差异在Miser模式中被禁用。",
        "apierror-spamdetected": "您的编辑被拒绝,因为它包含破坏性碎片:<code>$1</code>。",
        "apierror-specialpage-cantexecute": "您没有权限查看此特殊页面的结果。",
+       "apierror-stashedfilenotfound": "无法在暂存处找到文件:$1。",
        "apierror-stashfilestorage": "不能在暂存处存储上传:$1",
+       "apierror-stashinvalidfile": "无效暂存文件。",
        "apierror-stashnosuchfilekey": "没有这个filekey:$1。",
        "apierror-stashwrongowner": "错误所有者:$1",
        "apierror-stashzerolength": "文件长度为0,并且不能在暂存库中储存:$1。",
+       "apierror-systemblocked": "您已被MediaWiki自动封禁。",
        "apierror-templateexpansion-notwikitext": "模板展开只支持wiki文本内容。$1使用内容模型$2。",
        "apierror-unknownaction": "指定的操作<kbd>$1</kbd>不被承认。",
        "apierror-unknownerror-editpage": "未知的编辑页面错误:$1。",
        "apiwarn-invalidxmlstylesheetns": "样式表应位于{{ns:MediaWiki}}名字空间。",
        "apiwarn-moduleswithoutvars": "属性<kbd>modules</kbd>被设置,但不是<kbd>jsconfigvars</kbd>或<kbd>encodedjsconfigvars</kbd>。需要配置变量以获得适当的模块使用。",
        "apiwarn-notfile": "“$1”不是文件。",
+       "apiwarn-nothumb-noimagehandler": "不能创建缩略图,因为$1没有关联的图片处理器。",
        "apiwarn-parse-nocontentmodel": "<var>title</var>或<var>contentmodel</var>未提供,假设$1。",
        "apiwarn-parse-titlewithouttext": "<var>title</var>在没有<var>text</var>的情况下被使用,并且请求了已解析页面的属性。您是想用<var>page</var>而不是<var>title</var>么?",
        "apiwarn-tokennotallowed": "操作“$1”不允许当前用户使用。",
index e25f882..6d5f8c3 100644 (file)
@@ -154,7 +154,7 @@ abstract class FileCacheBase {
        /**
         * Save and compress text to the cache
         * @param string $text
-        * @return string Compressed text
+        * @return string|false Compressed text
         */
        public function saveText( $text ) {
                if ( $this->useGzip() ) {
index 4e6b2fd..0aca213 100644 (file)
@@ -22,6 +22,7 @@
  */
 use MediaWiki\MediaWikiServices;
 use Wikimedia\ScopedCallback;
+use MediaWiki\Logger\LoggerFactory;
 
 /**
  * MediaWiki message cache structure version.
@@ -52,6 +53,11 @@ class MessageCache {
         */
        protected $mCache;
 
+       /**
+        * @var bool[] Map of (language code => boolean)
+        */
+       protected $mCacheVolatile = [];
+
        /**
         * Should mean that database cannot be used, but check
         * @var bool $mDisable
@@ -65,10 +71,12 @@ class MessageCache {
        protected $mExpiry;
 
        /**
-        * Message cache has its own parser which it uses to transform
-        * messages.
+        * Message cache has its own parser which it uses to transform messages
+        * @var ParserOptions
         */
-       protected $mParserOptions, $mParser;
+       protected $mParserOptions;
+       /** @var Parser */
+       protected $mParser;
 
        /**
         * Variable for tracking which variables are already loaded
@@ -129,6 +137,7 @@ class MessageCache {
         */
        public static function normalizeKey( $key ) {
                global $wgContLang;
+
                $lckey = strtr( $key, ' ', '_' );
                if ( ord( $lckey ) < 128 ) {
                        $lckey[0] = strtolower( $lckey[0] );
@@ -258,6 +267,7 @@ class MessageCache {
                # Hash of the contents is stored in memcache, to detect if data-center cache
                # or local cache goes out of date (e.g. due to replace() on some other server)
                list( $hash, $hashVolatile ) = $this->getValidationHash( $code );
+               $this->mCacheVolatile[$code] = $hashVolatile;
 
                # Try the local cache and check against the cluster hash key...
                $cache = $this->getLocalCache( $code );
@@ -473,9 +483,16 @@ class MessageCache {
                $bigConds[] = 'page_len > ' . intval( $wgMaxMsgCacheEntrySize );
 
                # Load titles for all oversized pages in the MediaWiki namespace
-               $res = $dbr->select( 'page', 'page_title', $bigConds, __METHOD__ . "($code)-big" );
+               $res = $dbr->select(
+                       'page',
+                       [ 'page_title', 'page_latest' ],
+                       $bigConds,
+                       __METHOD__ . "($code)-big"
+               );
                foreach ( $res as $row ) {
                        $cache[$row->page_title] = '!TOO BIG';
+                       // At least include revision ID so page changes are reflected in the hash
+                       $cache['EXCESSIVE'][$row->page_title] = $row->page_latest;
                }
 
                # Conditions to load the remaining pages with their contents
@@ -525,7 +542,7 @@ class MessageCache {
         * Updates cache as necessary when message page is changed
         *
         * @param string|bool $title Name of the page changed (false if deleted)
-        * @param mixed $text New contents of the page.
+        * @param string|bool $text New contents of the page (false if deleted)
         */
        public function replace( $title, $text ) {
                global $wgMaxMsgCacheEntrySize, $wgContLang, $wgLanguageCode;
@@ -545,31 +562,32 @@ class MessageCache {
                // a self-deadlock. This is safe as no reads happen *directly* in this
                // method between getReentrantScopedLock() and load() below. There is
                // no risk of data "changing under our feet" for replace().
-               $cacheKey = wfMemcKey( 'messages', $code );
-               $scopedLock = $this->getReentrantScopedLock( $cacheKey );
+               $scopedLock = $this->getReentrantScopedLock( wfMemcKey( 'messages', $code ) );
+               // Load the messages from the master DB to avoid race conditions
                $this->load( $code, self::FOR_UPDATE );
 
-               $titleKey = wfMemcKey( 'messages', 'individual', $title );
+               // Load the new value into the process cache...
                if ( $text === false ) {
-                       // Article was deleted
                        $this->mCache[$code][$title] = '!NONEXISTENT';
-                       $this->wanCache->delete( $titleKey );
                } elseif ( strlen( $text ) > $wgMaxMsgCacheEntrySize ) {
-                       // Check for size
                        $this->mCache[$code][$title] = '!TOO BIG';
-                       $this->wanCache->set( $titleKey, ' ' . $text, $this->mExpiry );
+                       // Pre-fill the individual key cache with the known latest message text
+                       $key = $this->wanCache->makeKey( 'messages-big', $this->mCache[$code]['HASH'], $title );
+                       $this->wanCache->set( $key, " $text", $this->mExpiry );
                } else {
                        $this->mCache[$code][$title] = ' ' . $text;
-                       $this->wanCache->delete( $titleKey );
                }
-
-               // Mark this cache as definitely "latest" (non-volatile) so
-               // load() calls do try to refresh the cache with replica DB data
+               // Mark this cache as definitely being "latest" (non-volatile) so
+               // load() calls do not try to refresh the cache with replica DB data
                $this->mCache[$code]['LATEST'] = time();
 
                // Update caches if the lock was acquired
                if ( $scopedLock ) {
                        $this->saveToCaches( $this->mCache[$code], 'all', $code );
+               } else {
+                       LoggerFactory::getInstance( 'MessageCache' )->error(
+                               __METHOD__ . ': could not acquire lock to update {title} ({code})',
+                               [ 'title' => $title, 'code' => $code ] );
                }
 
                ScopedCallback::consume( $scopedLock );
@@ -650,24 +668,26 @@ class MessageCache {
        protected function getValidationHash( $code ) {
                $curTTL = null;
                $value = $this->wanCache->get(
-                       wfMemcKey( 'messages', $code, 'hash', 'v1' ),
+                       $this->wanCache->makeKey( 'messages', $code, 'hash', 'v1' ),
                        $curTTL,
                        [ wfMemcKey( 'messages', $code ) ]
                );
 
-               if ( !$value ) {
-                       // No hash found at all; cache must regenerate to be safe
-                       $hash = false;
-                       $expired = true;
-               } else {
+               if ( $value ) {
                        $hash = $value['hash'];
-                       if ( ( time() - $value['latest'] ) < WANObjectCache::HOLDOFF_TTL ) {
-                               // Cache was recently updated via replace() and should be up-to-date
+                       if ( ( time() - $value['latest'] ) < WANObjectCache::TTL_MINUTE ) {
+                               // Cache was recently updated via replace() and should be up-to-date.
+                               // That method is only called in the primary datacenter and uses FOR_UPDATE.
+                               // Also, it is unlikely that the current datacenter is *now* secondary one.
                                $expired = false;
                        } else {
                                // See if the "check" key was bumped after the hash was generated
                                $expired = ( $curTTL < 0 );
                        }
+               } else {
+                       // No hash found at all; cache must regenerate to be safe
+                       $hash = false;
+                       $expired = true;
                }
 
                return [ $hash, $expired ];
@@ -677,14 +697,15 @@ class MessageCache {
         * Set the md5 used to validate the local disk cache
         *
         * If $cache has a 'LATEST' UNIX timestamp key, then the hash will not
-        * be treated as "volatile" by getValidationHash() for the next few seconds
+        * be treated as "volatile" by getValidationHash() for the next few seconds.
+        * This is triggered when $cache is generated using FOR_UPDATE mode.
         *
         * @param string $code
         * @param array $cache Cached messages with a version
         */
        protected function setValidationHash( $code, array $cache ) {
                $this->wanCache->set(
-                       wfMemcKey( 'messages', $code, 'hash', 'v1' ),
+                       $this->wanCache->makeKey( 'messages', $code, 'hash', 'v1' ),
                        [
                                'hash' => $cache['HASH'],
                                'latest' => isset( $cache['LATEST'] ) ? $cache['LATEST'] : 0
@@ -847,6 +868,7 @@ class MessageCache {
         */
        private function getMessageForLang( $lang, $lckey, $useDB, &$alreadyTried ) {
                global $wgContLang;
+
                $langcode = $lang->getCode();
 
                // Try checking the database for the requested language
@@ -905,6 +927,7 @@ class MessageCache {
         */
        private function getMessagePageName( $langcode, $uckey ) {
                global $wgLanguageCode;
+
                if ( $langcode === $wgLanguageCode ) {
                        // Messages created in the content language will not have the /lang extension
                        return $uckey;
@@ -930,8 +953,7 @@ class MessageCache {
                if ( isset( $this->mCache[$code][$title] ) ) {
                        $entry = $this->mCache[$code][$title];
                        if ( substr( $entry, 0, 1 ) === ' ' ) {
-                               // The message exists, so make sure a string
-                               // is returned.
+                               // The message exists, so make sure a string is returned.
                                return (string)substr( $entry, 1 );
                        } elseif ( $entry === '!NONEXISTENT' ) {
                                return false;
@@ -950,17 +972,19 @@ class MessageCache {
                }
 
                // Try the individual message cache
-               $titleKey = wfMemcKey( 'messages', 'individual', $title );
-
-               $curTTL = null;
-               $entry = $this->wanCache->get(
-                       $titleKey,
-                       $curTTL,
-                       [ wfMemcKey( 'messages', $code ) ]
-               );
-               $entry = ( $curTTL >= 0 ) ? $entry : false;
+               $titleKey = $this->wanCache->makeKey( 'messages-big', $this->mCache[$code]['HASH'], $title );
+
+               if ( $this->mCacheVolatile[$code] ) {
+                       $entry = false;
+                       // Make sure that individual keys respect the WAN cache holdoff period too
+                       LoggerFactory::getInstance( 'MessageCache' )->debug(
+                               __METHOD__ . ': loading volatile key \'{titleKey}\'',
+                               [ 'titleKey' => $titleKey, 'code' => $code ] );
+               } else {
+                       $entry = $this->wanCache->get( $titleKey );
+               }
 
-               if ( $entry ) {
+               if ( $entry !== false ) {
                        if ( substr( $entry, 0, 1 ) === ' ' ) {
                                $this->mCache[$code][$title] = $entry;
                                // The message exists, so make sure a string is returned
@@ -975,7 +999,7 @@ class MessageCache {
                        }
                }
 
-               // Try loading it from the database
+               // Try loading the message from the database
                $dbr = wfGetDB( DB_REPLICA );
                $cacheOpts = Database::getCacheSetOptions( $dbr );
                // Use newKnownCurrent() to avoid querying revision/user tables
@@ -992,32 +1016,18 @@ class MessageCache {
 
                if ( $revision ) {
                        $content = $revision->getContent();
-                       if ( !$content ) {
-                               // A possibly temporary loading failure.
-                               wfDebugLog(
-                                       'MessageCache',
-                                       __METHOD__ . ": failed to load message page text for {$title} ($code)"
-                               );
-                               $message = null; // no negative caching
-                       } else {
-                               // XXX: Is this the right way to turn a Content object into a message?
-                               // NOTE: $content is typically either WikitextContent, JavaScriptContent or
-                               //       CssContent. MessageContent is *not* used for storing messages, it's
-                               //       only used for wrapping them when needed.
-                               $message = $content->getWikitextForTransclusion();
-
-                               if ( $message === false || $message === null ) {
-                                       wfDebugLog(
-                                               'MessageCache',
-                                               __METHOD__ . ": message content doesn't provide wikitext "
-                                                       . "(content model: " . $content->getModel() . ")"
-                                       );
-
-                                       $message = false; // negative caching
-                               } else {
+                       if ( $content ) {
+                               $message = $this->getMessageTextFromContent( $content );
+                               if ( is_string( $message ) ) {
                                        $this->mCache[$code][$title] = ' ' . $message;
                                        $this->wanCache->set( $titleKey, ' ' . $message, $this->mExpiry, $cacheOpts );
                                }
+                       } else {
+                               // A possibly temporary loading failure
+                               LoggerFactory::getInstance( 'MessageCache' )->warning(
+                                       __METHOD__ . ': failed to load message page text for \'{titleKey}\'',
+                                       [ 'titleKey' => $titleKey, 'code' => $code ] );
+                               $message = null; // no negative caching
                        }
                } else {
                        $message = false; // negative caching
@@ -1069,6 +1079,7 @@ class MessageCache {
         */
        function getParser() {
                global $wgParser, $wgParserConf;
+
                if ( !$this->mParser && isset( $wgParser ) ) {
                        # Do some initialisation so that we don't have to do it twice
                        $wgParser->firstCallInit();
@@ -1096,6 +1107,8 @@ class MessageCache {
        public function parse( $text, $title = null, $linestart = true,
                $interface = false, $language = null
        ) {
+               global $wgTitle;
+
                if ( $this->mInParser ) {
                        return htmlspecialchars( $text );
                }
@@ -1110,7 +1123,6 @@ class MessageCache {
                $popts->setTargetLanguage( $language );
 
                if ( !$title || !$title instanceof Title ) {
-                       global $wgTitle;
                        wfDebugLog( 'GlobalTitleFail', __METHOD__ . ' called by ' .
                                wfGetAllCallers( 6 ) . ' with no title set.' );
                        $title = $wgTitle;
@@ -1198,6 +1210,7 @@ class MessageCache {
         */
        public function getAllMessageKeys( $code ) {
                global $wgContLang;
+
                $this->load( $code );
                if ( !isset( $this->mCache[$code] ) ) {
                        // Apparently load() failed
@@ -1207,10 +1220,61 @@ class MessageCache {
                $cache = $this->mCache[$code];
                unset( $cache['VERSION'] );
                unset( $cache['EXPIRY'] );
+               unset( $cache['EXCESSIVE'] );
                // Remove any !NONEXISTENT keys
                $cache = array_diff( $cache, [ '!NONEXISTENT' ] );
 
                // Keys may appear with a capital first letter. lcfirst them.
                return array_map( [ $wgContLang, 'lcfirst' ], array_keys( $cache ) );
        }
+
+       /**
+        * Purge message caches when a MediaWiki: page is created, updated, or deleted
+        *
+        * @param Title $title Message page title
+        * @param Content|null $content New content for edit/create, null on deletion
+        * @since 1.29
+        */
+       public function updateMessageOverride( Title $title, Content $content = null ) {
+               global $wgContLang;
+
+               $msgText = $this->getMessageTextFromContent( $content );
+               if ( $msgText === null ) {
+                       $msgText = false; // treat as not existing
+               }
+
+               $this->replace( $title->getDBkey(), $msgText );
+
+               if ( $wgContLang->hasVariants() ) {
+                       $wgContLang->updateConversionTable( $title );
+               }
+       }
+
+       /**
+        * @param Content|null $content Content or null if the message page does not exist
+        * @return string|bool|null Returns false if $content is null and null on error
+        */
+       private function getMessageTextFromContent( Content $content = null ) {
+               // @TODO: could skip pseudo-messages like js/css here, based on content model
+               if ( $content ) {
+                       // Message page exists...
+                       // XXX: Is this the right way to turn a Content object into a message?
+                       // NOTE: $content is typically either WikitextContent, JavaScriptContent or
+                       //       CssContent. MessageContent is *not* used for storing messages, it's
+                       //       only used for wrapping them when needed.
+                       $msgText = $content->getWikitextForTransclusion();
+                       if ( $msgText === false || $msgText === null ) {
+                               // This might be due to some kind of misconfiguration...
+                               $msgText = null;
+                               LoggerFactory::getInstance( 'MessageCache' )->warning(
+                                       __METHOD__ . ": message content doesn't provide wikitext "
+                                       . "(content model: " . $content->getModel() . ")" );
+                       }
+               } else {
+                       // Message page does not exist...
+                       $msgText = false;
+               }
+
+               return $msgText;
+       }
 }
index 4b6362f..90b3de1 100644 (file)
@@ -313,7 +313,7 @@ class LocalisationCache {
         * array.
         * @param string $code
         * @param string $key
-        * @return bool|null|string
+        * @return bool|null|string|string[]
         */
        public function getSubitemList( $code, $key ) {
                if ( in_array( $key, self::$splitKeys ) ) {
index 515ab05..5d19961 100644 (file)
@@ -129,7 +129,7 @@ class CategoryMembershipChange {
                        $this->getUser(),
                        $this->getChangeMessageText(
                                $type,
-                               [ 'prefixedText' => $this->pageTitle->getPrefixedText() ],
+                               $this->pageTitle->getPrefixedText(),
                                $this->numTemplateLinks
                        ),
                        $this->pageTitle,
@@ -245,13 +245,12 @@ class CategoryMembershipChange {
         *
         * @param int $type may be CategoryMembershipChange::CATEGORY_ADDITION
         * or CategoryMembershipChange::CATEGORY_REMOVAL
-        * @param array $params
-        * - prefixedText: result of Title::->getPrefixedText()
+        * @param string $prefixedText result of Title::->getPrefixedText()
         * @param int $numTemplateLinks
         *
         * @return string
         */
-       private function getChangeMessageText( $type, array $params, $numTemplateLinks ) {
+       private function getChangeMessageText( $type, $prefixedText, $numTemplateLinks ) {
                $array = [
                        self::CATEGORY_ADDITION => 'recentchanges-page-added-to-category',
                        self::CATEGORY_REMOVAL => 'recentchanges-page-removed-from-category',
@@ -263,7 +262,7 @@ class CategoryMembershipChange {
                        $msgKey .= '-bundled';
                }
 
-               return wfMessage( $msgKey, $params )->inContentLanguage()->text();
+               return wfMessage( $msgKey, $prefixedText )->inContentLanguage()->text();
        }
 
        /**
index 9950a11..7659d6c 100644 (file)
@@ -63,6 +63,8 @@ abstract class Collation {
                                return new CollationCkb;
                        case 'xx-uca-et':
                                return new CollationEt;
+                       case 'xx-uca-fa':
+                               return new CollationFa;
                        default:
                                $match = [];
                                if ( preg_match( '/^uca-([a-z@=-]+)$/', $collationName, $match ) ) {
diff --git a/includes/collation/CollationFa.php b/includes/collation/CollationFa.php
new file mode 100644 (file)
index 0000000..b7e45cc
--- /dev/null
@@ -0,0 +1,44 @@
+<?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
+ */
+
+/**
+ * Temporary workaround for incorrect collation of Persian language ('fa') in ICU (bug T139110).
+ *
+ * 'ا' and 'و' should not be considered the same letter for the purposes of collation in Persian.
+ *
+ * @since 1.29
+ */
+class CollationFa extends IcuCollation {
+       private $tertiaryCollator;
+
+       public function __construct() {
+               parent::__construct( 'fa' );
+               $this->tertiaryCollator = Collator::create( 'fa' );
+       }
+
+       public function getPrimarySortKey( $string ) {
+               $firstLetter = mb_substr( $string, 0, 1 );
+               if ( $firstLetter === 'و' || $firstLetter === 'ا' ) {
+                       return $this->tertiaryCollator->getSortKey( $string );
+               }
+
+               return parent::getPrimarySortKey( $string );
+       }
+}
index 7b4fce6..bc5a209 100644 (file)
@@ -330,6 +330,7 @@ class IcuCollation extends Collation {
                        $cache = ObjectCache::getLocalServerInstance( CACHE_ANYTHING );
                        $cacheKey = $cache->makeKey(
                                'first-letters',
+                               get_class( $this ),
                                $this->locale,
                                $this->digitTransformLanguage->getCode(),
                                self::getICUVersion(),
index 931128f..6a0a63b 100644 (file)
@@ -381,7 +381,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param string|number $sectionId Section identifier as a number or string
+        * @param string|int $sectionId Section identifier as a number or string
         * (e.g. 0, 1 or 'T-1'). The ID "0" retrieves the section before the first heading, "1" the
         * text between the first heading (included) and the second heading (excluded), etc.
         *
@@ -396,7 +396,7 @@ interface Content {
         *
         * @since 1.21
         *
-        * @param string|number|null|bool $sectionId Section identifier as a number or string
+        * @param string|int|null|bool $sectionId Section identifier as a number or string
         * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole page
         * or 'new' for a new section.
         * @param Content $with New content of the section
index 9296728..d649baf 100644 (file)
@@ -38,7 +38,7 @@ class WikitextContent extends TextContent {
        }
 
        /**
-        * @param string|number $sectionId
+        * @param string|int $sectionId
         *
         * @return Content|bool|null
         *
@@ -58,7 +58,7 @@ class WikitextContent extends TextContent {
        }
 
        /**
-        * @param string|number|null|bool $sectionId
+        * @param string|int|null|bool $sectionId
         * @param Content $with
         * @param string $sectionTitle
         *
index f1ccd2a..2b394b6 100644 (file)
@@ -41,19 +41,19 @@ class CloneDatabase {
        /** @var bool Whether to use temporary tables or not */
        private $useTemporaryTables = true;
 
-       /** @var Database */
+       /** @var IMaintainableDatabase */
        private $db;
 
        /**
         * Constructor
         *
-        * @param Database $db A database subclass
+        * @param IMaintainableDatabase $db A database subclass
         * @param array $tablesToClone An array of tables to clone, unprefixed
         * @param string $newTablePrefix Prefix to assign to the tables
         * @param string $oldTablePrefix Prefix on current tables, if not $wgDBprefix
         * @param bool $dropCurrentTables
         */
-       public function __construct( Database $db, array $tablesToClone,
+       public function __construct( IMaintainableDatabase $db, array $tablesToClone,
                $newTablePrefix, $oldTablePrefix = '', $dropCurrentTables = true
        ) {
                $this->db = $db;
@@ -107,7 +107,8 @@ class CloneDatabase {
 
                        # Create new table
                        wfDebug( __METHOD__ . " duplicating $oldTableName to $newTableName\n" );
-                       $this->db->duplicateTableStructure( $oldTableName, $newTableName, $this->useTemporaryTables );
+                       $this->db->duplicateTableStructure(
+                               $oldTableName, $newTableName, $this->useTemporaryTables );
                }
        }
 
index 2f9f809..7c4bb3b 100644 (file)
@@ -332,7 +332,7 @@ class DatabaseMssql extends Database {
        }
 
        /**
-        * @return string
+        * @return string|int
         */
        public function lastErrno() {
                $err = sqlsrv_errors( SQLSRV_ERR_ALL );
index 9258506..c3502f6 100644 (file)
@@ -993,7 +993,7 @@ class DatabaseOracle extends Database {
         *
         * @param array|string $table
         * @param string $field
-        * @return ORAField|ORAResult
+        * @return ORAField|ORAResult|false
         */
        private function fieldInfoMulti( $table, $field ) {
                $field = strtoupper( $field );
index dde678f..87656f2 100644 (file)
@@ -147,8 +147,6 @@ class MWDebug {
         * @param string $log 'production' will always trigger a php error, 'auto'
         *    will trigger an error if $wgDevelopmentWarnings is true, and 'debug'
         *    will only write to the debug log(s).
-        *
-        * @return mixed
         */
        public static function warning( $msg, $callerOffset = 1, $level = E_USER_NOTICE, $log = 'auto' ) {
                global $wgDevelopmentWarnings;
index 4614c46..baf4637 100644 (file)
@@ -378,7 +378,7 @@ class LegacyLogger extends AbstractLogger {
                        if ( is_nan( $item ) ) {
                                return 'NaN';
                        }
-                       return $item;
+                       return (string)$item;
                }
 
                if ( is_scalar( $item ) ) {
index d38319e..a08bd9e 100644 (file)
@@ -67,7 +67,7 @@ abstract class DiffOp {
 
        /**
         * @param int $i
-        * @return string|null
+        * @return string[]|string|null
         */
        public function getClosing( $i = null ) {
                if ( $i === null ) {
index bd65fb4..559a5ec 100644 (file)
@@ -210,7 +210,7 @@ class DifferenceEngine extends ContextSource {
                if ( $link ) {
                        return "[$link $id]";
                } else {
-                       return $id;
+                       return (string)$id;
                }
        }
 
@@ -247,8 +247,9 @@ class DifferenceEngine extends ContextSource {
                Hooks::run( 'DifferenceEngineShowDiffPage', [ $out ] );
 
                if ( !$this->loadRevisionData() ) {
-                       $this->showMissingRevision();
-
+                       if ( Hooks::run( 'DifferenceEngineShowDiffPageMaybeShowMissingRevision', [ $this ] ) ) {
+                               $this->showMissingRevision();
+                       }
                        return;
                }
 
@@ -481,7 +482,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return string HTML or empty string
         */
-       protected function markPatrolledLink() {
+       public function markPatrolledLink() {
                if ( $this->mMarkPatrolledLink === null ) {
                        $linkInfo = $this->getMarkPatrolledLinkInfo();
                        // If false, there is no patrol link needed/allowed
@@ -1064,7 +1065,7 @@ class DifferenceEngine extends ContextSource {
         *
         * @return string HTML fragment
         */
-       protected function getRevisionHeader( Revision $rev, $complete = '' ) {
+       public function getRevisionHeader( Revision $rev, $complete = '' ) {
                $lang = $this->getLanguage();
                $user = $this->getUser();
                $revtimestamp = $rev->getTimestamp();
@@ -1369,6 +1370,7 @@ class DifferenceEngine extends ContextSource {
 
                if ( $this->mNewRev ) {
                        $this->mNewContent = $this->mNewRev->getContent( Revision::FOR_THIS_USER, $this->getUser() );
+                       Hooks::run( 'DifferenceEngineLoadTextAfterNewContentIsLoaded', [ $this ] );
                        if ( $this->mNewContent === null ) {
                                return false;
                        }
@@ -1395,6 +1397,8 @@ class DifferenceEngine extends ContextSource {
 
                $this->mNewContent = $this->mNewRev->getContent( Revision::FOR_THIS_USER, $this->getUser() );
 
+               Hooks::run( 'DifferenceEngineAfterLoadNewText', [ $this ] );
+
                return true;
        }
 
index 2f502d8..9b5a268 100644 (file)
@@ -24,7 +24,7 @@
  * @since 1.7
  * @ingroup Exception
  */
-class ErrorPageError extends MWException {
+class ErrorPageError extends MWException implements ILocalizedException {
        public $title, $msg, $params;
 
        /**
@@ -43,15 +43,23 @@ class ErrorPageError extends MWException {
                // customized by the local wiki. So get the default English version for
                // passing to the parent constructor. Our overridden report() below
                // makes sure that the page shown to the user is not forced to English.
-               if ( $msg instanceof Message ) {
-                       $enMsg = clone $msg;
-               } else {
-                       $enMsg = wfMessage( $msg, $params );
-               }
+               $enMsg = $this->getMessageObject();
                $enMsg->inLanguage( 'en' )->useDatabase( false );
                parent::__construct( $enMsg->text() );
        }
 
+       /**
+        * Return a Message object for this exception
+        * @since 1.29
+        * @return Message
+        */
+       public function getMessageObject() {
+               if ( $this->msg instanceof Message ) {
+                       return clone $this->msg;
+               }
+               return wfMessage( $this->msg, $this->params );
+       }
+
        public function report() {
                global $wgOut;
 
diff --git a/includes/exception/LocalizedException.php b/includes/exception/LocalizedException.php
new file mode 100644 (file)
index 0000000..cbdb53e
--- /dev/null
@@ -0,0 +1,66 @@
+<?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
+ */
+
+/**
+ * Interface for MediaWiki-localized exceptions
+ *
+ * @since 1.29
+ * @ingroup Exception
+ */
+interface ILocalizedException {
+       /**
+        * Return a Message object for this exception
+        * @return Message
+        */
+       public function getMessageObject();
+}
+
+/**
+ * Basic localized exception.
+ *
+ * @since 1.29
+ * @ingroup Exception
+ * @note Don't use this in a situation where MessageCache is not functional.
+ */
+class LocalizedException extends Exception implements ILocalizedException {
+       /** @var string|array|MessageSpecifier */
+       protected $messageSpec;
+
+       /**
+        * @param string|array|MessageSpecifier $messageSpec See Message::newFromSpecifier
+        * @param int $code Exception code
+        * @param Exception|Throwable $previous The previous exception used for the exception chaining.
+        */
+       public function __construct( $messageSpec, $code = 0, $previous = null ) {
+               $this->messageSpec = $messageSpec;
+
+               // Exception->getMessage() should be in plain English, not localized.
+               // So fetch the English version of the message, without local
+               // customizations, and make a basic attempt to turn markup into text.
+               $msg = $this->getMessageObject()->inLanguage( 'en' )->useDatabase( false )->text();
+               $msg = preg_replace( '!</?(var|kbd|samp|code)>!', '"', $msg );
+               $msg = html_entity_decode( strip_tags( $msg ), ENT_QUOTES | ENT_HTML5 );
+               parent::__construct( $msg, $code, $previous );
+       }
+
+       public function getMessageObject() {
+               return Message::newFromSpecifier( $this->messageSpec );
+       }
+}
index 3d8ddb8..bef379e 100644 (file)
@@ -26,6 +26,8 @@ use MediaWiki\MediaWikiServices;
  * @ingroup Exception
  */
 class MWExceptionHandler {
+       const CAUGHT_BY_HANDLER = 'mwe_handler'; // error reported by this exception handler
+       const CAUGHT_BY_OTHER = 'other'; // error reported by direct logException() call
 
        /**
         * @var string $reservedMemory
@@ -130,10 +132,10 @@ class MWExceptionHandler {
                        // which would result in an exception loop. PHP may escalate such
                        // errors to "Exception thrown without a stack frame" fatals, but
                        // it's better to be explicit here.
-                       self::logException( $e2 );
+                       self::logException( $e2, self::CAUGHT_BY_HANDLER );
                }
 
-               self::logException( $e );
+               self::logException( $e, self::CAUGHT_BY_HANDLER );
                self::report( $e );
 
                // Exit value should be nonzero for the benefit of shell jobs
@@ -293,6 +295,7 @@ TXT;
                                'trace' => static::redactTrace( $trace ),
                        ],
                        'exception_id' => wfRandomString( 8 ),
+                       'caught_by' => self::CAUGHT_BY_HANDLER
                ] );
 
                // Remember call so we don't double process via HHVM's fatal
@@ -464,12 +467,14 @@ TXT;
         * logger.
         *
         * @param Exception|Throwable $e
+        * @param string $catcher CAUGHT_BY_* class constant indicating what caught the error
         * @return array
         */
-       public static function getLogContext( $e ) {
+       public static function getLogContext( $e, $catcher = self::CAUGHT_BY_OTHER ) {
                return [
                        'exception' => $e,
                        'exception_id' => WebRequest::getRequestId(),
+                       'caught_by' => $catcher
                ];
        }
 
@@ -481,11 +486,13 @@ TXT;
         * will be redacted as per getRedactedTraceAsArray().
         *
         * @param Exception|Throwable $e
+        * @param string $catcher CAUGHT_BY_* class constant indicating what caught the error
         * @return array
         * @since 1.26
         */
-       public static function getStructuredExceptionData( $e ) {
+       public static function getStructuredExceptionData( $e, $catcher = self::CAUGHT_BY_OTHER ) {
                global $wgLogExceptionBacktrace;
+
                $data = [
                        'id' => WebRequest::getRequestId(),
                        'type' => get_class( $e ),
@@ -494,6 +501,7 @@ TXT;
                        'message' => $e->getMessage(),
                        'code' => $e->getCode(),
                        'url' => self::getURL() ?: null,
+                       'caught_by' => $catcher
                ];
 
                if ( $e instanceof ErrorException &&
@@ -509,7 +517,7 @@ TXT;
 
                $previous = $e->getPrevious();
                if ( $previous !== null ) {
-                       $data['previous'] = self::getStructuredExceptionData( $previous );
+                       $data['previous'] = self::getStructuredExceptionData( $previous, $catcher );
                }
 
                return $data;
@@ -566,11 +574,17 @@ TXT;
         * @param Exception|Throwable $e
         * @param bool $pretty Add non-significant whitespace to improve readability (default: false).
         * @param int $escaping Bitfield consisting of FormatJson::.*_OK class constants.
+        * @param string $catcher CAUGHT_BY_* class constant indicating what caught the error
         * @return string|false JSON string if successful; false upon failure
         */
-       public static function jsonSerializeException( $e, $pretty = false, $escaping = 0 ) {
-               $data = self::getStructuredExceptionData( $e );
-               return FormatJson::encode( $data, $pretty, $escaping );
+       public static function jsonSerializeException(
+               $e, $pretty = false, $escaping = 0, $catcher = self::CAUGHT_BY_OTHER
+       ) {
+               return FormatJson::encode(
+                       self::getStructuredExceptionData( $e, $catcher ),
+                       $pretty,
+                       $escaping
+               );
        }
 
        /**
@@ -581,16 +595,17 @@ TXT;
         *
         * @since 1.22
         * @param Exception|Throwable $e
+        * @param string $catcher CAUGHT_BY_* class constant indicating what caught the error
         */
-       public static function logException( $e ) {
+       public static function logException( $e, $catcher = self::CAUGHT_BY_OTHER ) {
                if ( !( $e instanceof MWException ) || $e->isLoggable() ) {
                        $logger = LoggerFactory::getInstance( 'exception' );
                        $logger->error(
                                self::getLogMessage( $e ),
-                               self::getLogContext( $e )
+                               self::getLogContext( $e, $catcher )
                        );
 
-                       $json = self::jsonSerializeException( $e, false, FormatJson::ALL_OK );
+                       $json = self::jsonSerializeException( $e, false, FormatJson::ALL_OK, $catcher );
                        if ( $json !== false ) {
                                $logger = LoggerFactory::getInstance( 'exception-json' );
                                $logger->error( $json, [ 'private' => true ] );
@@ -608,6 +623,7 @@ TXT;
         * @param string $channel
        */
        protected static function logError( ErrorException $e, $channel ) {
+               $catcher = self::CAUGHT_BY_HANDLER;
                // The set_error_handler callback is independent from error_reporting.
                // Filter out unwanted errors manually (e.g. when
                // MediaWiki\suppressWarnings is active).
@@ -616,12 +632,12 @@ TXT;
                        $logger = LoggerFactory::getInstance( $channel );
                        $logger->error(
                                self::getLogMessage( $e ),
-                               self::getLogContext( $e )
+                               self::getLogContext( $e, $catcher )
                        );
                }
 
                // Include all errors in the json log (surpressed errors will be flagged)
-               $json = self::jsonSerializeException( $e, false, FormatJson::ALL_OK );
+               $json = self::jsonSerializeException( $e, false, FormatJson::ALL_OK, $catcher );
                if ( $json !== false ) {
                        $logger = LoggerFactory::getInstance( "{$channel}-json" );
                        $logger->error( $json, [ 'private' => true ] );
index b600f42..a569bcd 100644 (file)
@@ -207,14 +207,14 @@ class MWExceptionRenderer {
         */
        public static function getHTML( $e ) {
                if ( self::showBackTrace( $e ) ) {
-                       $html = "<div class=\"errorbox\"><p>" .
+                       $html = "<div class=\"errorbox mw-content-ltr\"><p>" .
                                nl2br( htmlspecialchars( MWExceptionHandler::getLogMessage( $e ) ) ) .
                                '</p><p>Backtrace:</p><p>' .
                                nl2br( htmlspecialchars( MWExceptionHandler::getRedactedTraceAsString( $e ) ) ) .
                                "</p></div>\n";
                } else {
                        $logId = WebRequest::getRequestId();
-                       $html = "<div class=\"errorbox\">" .
+                       $html = "<div class=\"errorbox mw-content-ltr\">" .
                                '[' . $logId . '] ' .
                                gmdate( 'Y-m-d H:i:s' ) . ": " .
                                self::msg( "internalerror-fatal-exception",
index e31374c..5ecd237 100644 (file)
@@ -58,6 +58,9 @@ class PermissionsError extends ErrorPageError {
                }
 
                $this->errors = $errors;
+
+               // Give the parent class something to work with
+               parent::__construct( 'permissionserrors', Message::newFromSpecifier( $errors[0] ) );
        }
 
        public function report() {
index ab26803..5be166b 100644 (file)
@@ -38,7 +38,7 @@ class XmlDumpWriter {
         * @return string
         */
        function openStream() {
-               global $wgLanguageCode;
+               global $wgContLang;
                $ver = WikiExporter::schemaVersion();
                return Xml::element( 'mediawiki', [
                        'xmlns'              => "http://www.mediawiki.org/xml/export-$ver/",
@@ -56,7 +56,7 @@ class XmlDumpWriter {
                        'xsi:schemaLocation' => "http://www.mediawiki.org/xml/export-$ver/ " .
                                "http://www.mediawiki.org/xml/export-$ver.xsd",
                        'version'            => $ver,
-                       'xml:lang'           => $wgLanguageCode ],
+                       'xml:lang'           => $wgContLang->getHtmlCode() ],
                        null ) .
                        "\n" .
                        $this->siteInfo();
index 7e93299..52c1a4c 100644 (file)
@@ -105,7 +105,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @param string $cluster Cluster name
         * @return LoadBalancer
         */
-       function getLoadBalancer( $cluster ) {
+       private function getLoadBalancer( $cluster ) {
                $wiki = isset( $this->params['wiki'] ) ? $this->params['wiki'] : false;
 
                return wfGetLBFactory()->getExternalLB( $cluster, $wiki );
@@ -115,9 +115,9 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * Get a replica DB connection for the specified cluster
         *
         * @param string $cluster Cluster name
-        * @return IDatabase
+        * @return DBConnRef
         */
-       function getSlave( $cluster ) {
+       public function getSlave( $cluster ) {
                global $wgDefaultExternalStore;
 
                $wiki = isset( $this->params['wiki'] ) ? $this->params['wiki'] : false;
@@ -140,13 +140,13 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * Get a master database connection for the specified cluster
         *
         * @param string $cluster Cluster name
-        * @return IDatabase
+        * @return MaintainableDBConnRef
         */
-       function getMaster( $cluster ) {
+       public function getMaster( $cluster ) {
                $wiki = isset( $this->params['wiki'] ) ? $this->params['wiki'] : false;
                $lb = $this->getLoadBalancer( $cluster );
 
-               $db = $lb->getConnectionRef( DB_MASTER, [], $wiki );
+               $db = $lb->getMaintenanceConnectionRef( DB_MASTER, [], $wiki );
                $db->clearFlag( DBO_TRX ); // sanity
 
                return $db;
@@ -158,7 +158,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @param IDatabase $db
         * @return string Table name ('blobs' by default)
         */
-       function getTable( $db ) {
+       public function getTable( $db ) {
                $table = $db->getLBInfo( 'blobs table' );
                if ( is_null( $table ) ) {
                        $table = 'blobs';
@@ -175,9 +175,8 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @param string $id
         * @param string $itemID
         * @return HistoryBlob|bool Returns false if missing
-        * @private
         */
-       function fetchBlob( $cluster, $id, $itemID ) {
+       private function fetchBlob( $cluster, $id, $itemID ) {
                /**
                 * One-step cache variable to hold base blobs; operations that
                 * pull multiple revisions may often pull multiple times from
@@ -230,7 +229,7 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * @return array A map from the blob_id's requested to their content.
         *   Unlocated ids are not represented
         */
-       function batchFetchBlobs( $cluster, array $ids ) {
+       private function batchFetchBlobs( $cluster, array $ids ) {
                $dbr = $this->getSlave( $cluster );
                $res = $dbr->select( $this->getTable( $dbr ),
                        [ 'blob_id', 'blob_text' ], [ 'blob_id' => array_keys( $ids ) ], __METHOD__ );
diff --git a/includes/filerepo/FSRepo.php b/includes/filerepo/FSRepo.php
deleted file mode 100644 (file)
index d06acf2..0000000
+++ /dev/null
@@ -1,81 +0,0 @@
-<?php
-/**
- * A repository for files accessible via the local filesystem.
- *
- * 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 FileRepo
- */
-
-/**
- * A repository for files accessible via the local filesystem.
- * Does not support database access or registration.
- *
- * This is a mostly a legacy class. New uses should not be added.
- *
- * @ingroup FileRepo
- * @deprecated since 1.19
- */
-class FSRepo extends FileRepo {
-       /**
-        * @param array $info
-        * @throws MWException
-        */
-       function __construct( array $info ) {
-               if ( !isset( $info['backend'] ) ) {
-                       // B/C settings...
-                       $directory = $info['directory'];
-                       $deletedDir = isset( $info['deletedDir'] )
-                               ? $info['deletedDir']
-                               : false;
-                       $thumbDir = isset( $info['thumbDir'] )
-                               ? $info['thumbDir']
-                               : "{$directory}/thumb";
-                       $transcodedDir = isset( $info['transcodedDir'] )
-                               ? $info['transcodedDir']
-                               : "{$directory}/transcoded";
-                       $fileMode = isset( $info['fileMode'] )
-                               ? $info['fileMode']
-                               : 0644;
-
-                       $repoName = $info['name'];
-                       // Get the FS backend configuration
-                       $backend = new FSFileBackend( [
-                               'name' => $info['name'] . '-backend',
-                               'wikiId' => wfWikiID(),
-                               'lockManager' => LockManagerGroup::singleton( wfWikiID() )->get( 'fsLockManager' ),
-                               'containerPaths' => [
-                                       "{$repoName}-public" => "{$directory}",
-                                       "{$repoName}-temp" => "{$directory}/temp",
-                                       "{$repoName}-thumb" => $thumbDir,
-                                       "{$repoName}-transcoded" => $transcodedDir,
-                                       "{$repoName}-deleted" => $deletedDir
-                               ],
-                               'fileMode' => $fileMode,
-                               'tmpDirectory' => wfTempDir()
-                       ] );
-                       // Update repo config to use this backend
-                       $info['backend'] = $backend;
-               }
-
-               parent::__construct( $info );
-
-               if ( !( $this->backend instanceof FSFileBackend ) ) {
-                       throw new MWException( "FSRepo only supports FSFileBackend." );
-               }
-       }
-}
index 66dab99..0e4b2f0 100644 (file)
@@ -99,7 +99,7 @@ class FileRepo {
         */
        protected $pathDisclosureProtection = 'simple';
 
-       /** @var bool Public zone URL. */
+       /** @var string|false Public zone URL. */
        protected $url;
 
        /** @var string The base thumbnail URL. Defaults to "<url>/thumb". */
@@ -309,7 +309,7 @@ class FileRepo {
         * @return bool Whether non-ASCII path characters are allowed
         */
        public function backendSupportsUnicodePaths() {
-               return ( $this->getBackend()->getFeatures() & FileBackend::ATTR_UNICODE_PATHS );
+               return (bool)( $this->getBackend()->getFeatures() & FileBackend::ATTR_UNICODE_PATHS );
        }
 
        /**
@@ -737,7 +737,7 @@ class FileRepo {
         * constructor, whereas local repositories use the local Title functions.
         *
         * @param string $name
-        * @return string
+        * @return string|false
         */
        public function getDescriptionUrl( $name ) {
                $encName = wfUrlencode( $name );
@@ -771,7 +771,7 @@ class FileRepo {
         *
         * @param string $name Name of image to fetch
         * @param string $lang Language to fetch it in, if any.
-        * @return string
+        * @return string|false
         */
        public function getDescriptionRenderUrl( $name, $lang = null ) {
                $query = 'action=render';
@@ -1059,7 +1059,7 @@ class FileRepo {
 
        /**
         * Pick a random name in the temp zone and store a file to it.
-        * Returns a FileRepoStatus object with the file Virtual URL in the value,
+        * Returns a Status object with the file Virtual URL in the value,
         * file can later be disposed using FileRepo::freeTemp().
         *
         * @param string $originalName The base name of the file as specified
@@ -1143,7 +1143,7 @@ class FileRepo {
         * Copy or move a file either from a storage path, virtual URL,
         * or file system path, into this repository at the specified destination location.
         *
-        * Returns a FileRepoStatus object. On success, the value contains "new" or
+        * Returns a Status object. On success, the value contains "new" or
         * "archived", to indicate whether the file was new with that name.
         *
         * Options to $options include:
@@ -1924,12 +1924,3 @@ class FileRepo {
                return $this->supportsSha1URLs;
        }
 }
-
-/**
- * FileRepo for temporary files created via FileRepo::getTempRepo()
- */
-class TempFileRepo extends FileRepo {
-       public function getTempRepo() {
-               throw new MWException( "Cannot get a temp repo from a temp repo." );
-       }
-}
index 4176c82..ca41718 100644 (file)
@@ -109,7 +109,7 @@ class ForeignAPIRepo extends FileRepo {
         *
         * @param Title $title
         * @param string|bool $time
-        * @return File
+        * @return File|false
         */
        function newFile( $title, $time = false ) {
                if ( $time ) {
index d47624f..2edd6d0 100644 (file)
@@ -334,7 +334,7 @@ class RepoGroup {
        /**
         * Get the repo instance by its name
         * @param string $name
-        * @return bool
+        * @return FileRepo|bool
         */
        function getRepoByName( $name ) {
                if ( !$this->reposInitialised ) {
diff --git a/includes/filerepo/TempFileRepo.php b/includes/filerepo/TempFileRepo.php
new file mode 100644 (file)
index 0000000..c9a6b59
--- /dev/null
@@ -0,0 +1,9 @@
+<?php
+/**
+ * FileRepo for temporary files created via FileRepo::getTempRepo()
+ */
+class TempFileRepo extends FileRepo {
+       public function getTempRepo() {
+               throw new MWException( "Cannot get a temp repo from a temp repo." );
+       }
+}
index 921e129..9a7a55b 100644 (file)
@@ -81,7 +81,7 @@ class ArchivedFile {
        /** @var string SHA-1 hash of file content */
        private $sha1;
 
-       /** @var string Number of pages of a multipage document, or false for
+       /** @var int|false Number of pages of a multipage document, or false for
         * documents which aren't multipage documents
         */
        private $pageCount;
@@ -496,7 +496,7 @@ class ArchivedFile {
         * Return the user name of the uploader.
         *
         * @deprecated since 1.23 Use getUser( 'text' ) instead.
-        * @return string
+        * @return string|int
         */
        public function getUserText() {
                wfDeprecated( __METHOD__, '1.23' );
@@ -511,7 +511,7 @@ class ArchivedFile {
        /**
         * Return upload description.
         *
-        * @return string
+        * @return string|int
         */
        public function getDescription() {
                $this->load();
index 9188cd9..be78462 100644 (file)
@@ -127,7 +127,7 @@ abstract class File implements IDBAccessObject {
        /** @var string Relative path including trailing slash */
        protected $hashPath;
 
-       /** @var string Number of pages of a multipage document, or false for
+       /** @var string|false Number of pages of a multipage document, or false for
         *    documents which aren't multipage documents
         */
        protected $pageCount;
@@ -535,7 +535,7 @@ abstract class File implements IDBAccessObject {
        /**
         * Get the duration of a media file in seconds
         *
-        * @return int
+        * @return float|int
         */
        public function getLength() {
                $handler = $this->getHandler();
@@ -909,7 +909,7 @@ abstract class File implements IDBAccessObject {
         *
         * @param array $handlerParams
         *
-        * @return string
+        * @return ThumbnailImage|MediaTransformOutput|bool False on failure
         */
        function getUnscaledThumb( $handlerParams = [] ) {
                $hp =& $handlerParams;
@@ -1792,7 +1792,7 @@ abstract class File implements IDBAccessObject {
 
        /**
         * Move or copy a file to its public location. If a file exists at the
-        * destination, move it to an archive. Returns a FileRepoStatus object with
+        * destination, move it to an archive. Returns a Status object with
         * the archive name in the "value" member on success.
         *
         * The archive name should be passed through to recordUpload for database
@@ -1963,7 +1963,7 @@ abstract class File implements IDBAccessObject {
         * Returns the number of pages of a multipage document, or false for
         * documents which aren't multipage documents
         *
-        * @return bool|int
+        * @return string|bool|int
         */
        function pageCount() {
                if ( !isset( $this->pageCount ) ) {
@@ -1991,7 +1991,7 @@ abstract class File implements IDBAccessObject {
                if ( $srcWidth == 0 ) {
                        return 0;
                } else {
-                       return round( $srcHeight * $dstWidth / $srcWidth );
+                       return (int)round( $srcHeight * $dstWidth / $srcWidth );
                }
        }
 
@@ -2003,7 +2003,7 @@ abstract class File implements IDBAccessObject {
         *  a good reason. This method skips all caches.
         *
         * @param string $filePath The path to the file (e.g. From getLocalPathRef() )
-        * @return array The width, followed by height, with optionally more things after
+        * @return array|false The width, followed by height, with optionally more things after
         */
        function getImageSize( $filePath ) {
                if ( !$this->getHandler() ) {
@@ -2031,7 +2031,7 @@ abstract class File implements IDBAccessObject {
         * Get the HTML text of the description page, if available
         *
         * @param bool|Language $lang Optional language to fetch description in
-        * @return string
+        * @return string|false
         */
        function getDescriptionText( $lang = false ) {
                global $wgLang;
@@ -2122,7 +2122,7 @@ abstract class File implements IDBAccessObject {
        /**
         * Get the deletion archive key, "<sha1>.<ext>"
         *
-        * @return string
+        * @return string|false
         */
        function getStorageKey() {
                $hash = $this->getSha1();
index df50a67..c6c49b4 100644 (file)
@@ -121,7 +121,7 @@ class ForeignDBFile extends LocalFile {
 
        /**
         * @param bool|Language $lang Optional language to fetch description in.
-        * @return string
+        * @return string|false
         */
        function getDescriptionText( $lang = false ) {
                global $wgLang;
index 011ba87..16fe72d 100644 (file)
@@ -1572,7 +1572,7 @@ class LocalFile extends File {
 
        /**
         * Move or copy a file to its public location. If a file exists at the
-        * destination, move it to an archive. Returns a FileRepoStatus object with
+        * destination, move it to an archive. Returns a Status object with
         * the archive name in the "value" member on success.
         *
         * The archive name should be passed through to recordUpload for database
@@ -1590,7 +1590,7 @@ class LocalFile extends File {
        }
 
        /**
-        * Move or copy a file to a specified location. Returns a FileRepoStatus
+        * Move or copy a file to a specified location. Returns a Status
         * object with the archive name in the "value" member on success.
         *
         * The archive name should be passed through to recordUpload for database
@@ -2086,7 +2086,7 @@ class LocalFileDeleteBatch {
        /** @var bool Whether to suppress all suppressable fields when deleting */
        private $suppress;
 
-       /** @var FileRepoStatus */
+       /** @var Status */
        private $status;
 
        /** @var User */
@@ -2993,7 +2993,7 @@ class LocalFileMoveBatch {
        }
 
        /**
-        * Verify the database updates and return a new FileRepoStatus indicating how
+        * Verify the database updates and return a new Status indicating how
         * many rows would be updated.
         *
         * @return Status
@@ -3036,7 +3036,7 @@ class LocalFileMoveBatch {
        }
 
        /**
-        * Do the database updates and return a new FileRepoStatus indicating how
+        * Do the database updates and return a new Status indicating how
         * many rows where updated.
         */
        protected function doDBUpdates() {
index 71ccaa3..5c5a9a7 100644 (file)
@@ -1047,6 +1047,7 @@ class HTMLForm extends ContextSource {
                        : 'application/x-www-form-urlencoded';
                # Attributes
                $attribs = [
+                       'class' => 'mw-htmlform',
                        'action' => $this->getAction(),
                        'method' => $this->getMethod(),
                        'enctype' => $encType,
@@ -1079,7 +1080,7 @@ class HTMLForm extends ContextSource {
 
                return Html::rawElement(
                        'form',
-                       $this->getFormAttributes() + [ 'class' => 'visualClear' ],
+                       $this->getFormAttributes(),
                        $html
                );
        }
index 71aa275..804bbff 100644 (file)
@@ -1034,7 +1034,7 @@ abstract class HTMLFormField {
         * with integer 0 as a value.
         *
         * @param array $array
-        * @return array
+        * @return array|string
         */
        public static function forceToStringRecursive( $array ) {
                if ( is_array( $array ) ) {
index 46b570d..54bdf04 100644 (file)
@@ -275,7 +275,7 @@ class OOUIHTMLForm extends HTMLForm {
 
        public function wrapForm( $html ) {
                $form = new OOUI\FormLayout( $this->getFormAttributes() + [
-                       'classes' => [ 'mw-htmlform-ooui' ],
+                       'classes' => [ 'mw-htmlform', 'mw-htmlform-ooui' ],
                        'content' => new OOUI\HtmlSnippet( $html ),
                ] );
 
index 5d9f7a0..325526b 100644 (file)
@@ -67,7 +67,7 @@ class VFormHTMLForm extends HTMLForm {
 
        protected function getFormAttributes() {
                $attribs = parent::getFormAttributes();
-               $attribs['class'] = [ 'mw-ui-vform', 'mw-ui-container', 'visualClear' ];
+               $attribs['class'] = [ 'mw-htmlform', 'mw-ui-vform', 'mw-ui-container' ];
                return $attribs;
        }
 
index 285490b..a19bd5a 100644 (file)
@@ -13,6 +13,9 @@
  *   of the value from 'default'. Overrides 'buttonlabel-raw'.
  * - buttonlabel-raw: HTMLto display for the button display text, instead
  *   of the value from 'default'.
+ * - formnovalidate: Set to true if clicking this button should suppress
+ *   client-side form validation. Used in HTMLFormFieldCloner for add/remove
+ *   buttons.
  *
  * Note that the buttonlabel parameters are not supported on IE6 and IE7 due to
  * bugs in those browsers. If detected, they will be served buttons using the
@@ -27,12 +30,18 @@ class HTMLButtonField extends HTMLFormField {
        /** @var array $mFlags Flags to add to OOUI Button widget */
        protected $mFlags = [];
 
+       protected $mFormnovalidate = false;
+
        public function __construct( $info ) {
                $info['nodata'] = true;
                if ( isset( $info['flags'] ) ) {
                        $this->mFlags = $info['flags'];
                }
 
+               if ( isset( $info['formnovalidate'] ) ) {
+                       $this->mFormnovalidate = $info['formnovalidate'];
+               }
+
                # Generate the label from a message, if possible
                if ( isset( $info['buttonlabel-message'] ) ) {
                        $this->buttonLabel = $this->getMessage( $info['buttonlabel-message'] )->parse();
@@ -71,6 +80,7 @@ class HTMLButtonField extends HTMLFormField {
                        'type' => $this->buttonType,
                        'name' => $this->mName,
                        'value' => $this->getDefault(),
+                       'formnovalidate' => $this->mFormnovalidate,
                ] + $this->getAttributes( [ 'disabled', 'tabindex' ] );
 
                if ( $this->isBadIE() ) {
@@ -127,6 +137,6 @@ class HTMLButtonField extends HTMLFormField {
                $request = $this->mParent
                        ? $this->mParent->getRequest()
                        : RequestContext::getMain()->getRequest();
-               return preg_match( '/MSIE [1-7]\./i', $request->getHeader( 'User-Agent' ) );
+               return (bool)preg_match( '/MSIE [1-7]\./i', $request->getHeader( 'User-Agent' ) );
        }
 }
index a871584..8fb840a 100644 (file)
@@ -57,6 +57,7 @@ class HTMLFormFieldCloner extends HTMLFormField {
                if ( isset( $this->mParams['fields']['delete'] ) ) {
                        $class = 'mw-htmlform-cloner-delete-button';
                        $info = $this->mParams['fields']['delete'] + [
+                               'formnovalidate' => true,
                                'cssclass' => $class
                        ];
                        unset( $info['name'], $info['class'] );
@@ -96,6 +97,17 @@ class HTMLFormFieldCloner extends HTMLFormField {
                        } else {
                                $info['id'] = Sanitizer::escapeId( "{$this->mID}--$key--$fieldname" );
                        }
+                       // Copy the hide-if rules to "child" fields, so that the JavaScript code handling them
+                       // (resources/src/mediawiki/htmlform/hide-if.js) doesn't have to handle nested fields.
+                       if ( $this->mHideIf ) {
+                               if ( isset( $info['hide-if'] ) ) {
+                                       // Hide child field if either its rules say it's hidden, or parent's rules say it's hidden
+                                       $info['hide-if'] = [ 'OR', $info['hide-if'], $this->mHideIf ];
+                               } else {
+                                       // Hide child field if parent's rules say it's hidden
+                                       $info['hide-if'] = $this->mHideIf;
+                               }
+                       }
                        $field = HTMLForm::loadInputFromParameters( $name, $info, $this->mParent );
                        $fields[$fieldname] = $field;
                }
@@ -299,6 +311,7 @@ class HTMLFormFieldCloner extends HTMLFormField {
                                : 'htmlform-cloner-delete';
                        $field = HTMLForm::loadInputFromParameters( $name, [
                                'type' => 'submit',
+                               'formnovalidate' => true,
                                'name' => $name,
                                'id' => Sanitizer::escapeId( "{$this->mID}--$key--delete" ),
                                'cssclass' => 'mw-htmlform-cloner-delete-button',
@@ -371,6 +384,7 @@ class HTMLFormFieldCloner extends HTMLFormField {
                        : 'htmlform-cloner-create';
                $field = HTMLForm::loadInputFromParameters( $name, [
                        'type' => 'submit',
+                       'formnovalidate' => true,
                        'name' => $name,
                        'id' => Sanitizer::escapeId( "{$this->mID}--create" ),
                        'cssclass' => 'mw-htmlform-cloner-create-button',
index 05a2ba6..23044bd 100644 (file)
@@ -149,7 +149,7 @@ class HTMLMultiSelectField extends HTMLFormField implements HTMLNestedFilterable
        /**
         * @param WebRequest $request
         *
-        * @return string
+        * @return string|array
         */
        public function loadDataFromRequest( $request ) {
                if ( $this->isSubmitAttempt( $request ) ) {
index d94eb8d..5ad7ee3 100644 (file)
@@ -49,7 +49,7 @@ class HTMLSizeFilterField extends HTMLIntField {
        /**
         * @param WebRequest $request
         *
-        * @return string
+        * @return string|int
         */
        public function loadDataFromRequest( $request ) {
                $size = $request->getInt( $this->mName );
index 8255bb3..779d606 100644 (file)
@@ -142,7 +142,7 @@ class Http {
         * @return bool
         */
        public static function isValidURI( $uri ) {
-               return preg_match(
+               return (bool)preg_match(
                        '/^https?:\/\/[^\/\s]\S*$/D',
                        $uri
                );
index 03f9974..9dc8032 100644 (file)
@@ -567,7 +567,7 @@ abstract class Installer {
        /**
         * Determine if LocalSettings.php exists. If it does, return its variables.
         *
-        * @return array
+        * @return array|false
         */
        public static function getExistingLocalSettings() {
                global $IP;
@@ -1080,7 +1080,7 @@ abstract class Installer {
        /**
         * Convert a hex string representing a Unicode code point to that code point.
         * @param string $c
-        * @return string
+        * @return string|false
         */
        protected function unicodeChar( $c ) {
                $c = hexdec( $c );
index a9e3e85..697188e 100644 (file)
@@ -109,7 +109,7 @@ class LocalSettingsGenerator {
         *
         * @param string $string
         *
-        * @return string
+        * @return string|false
         */
        public static function escapePhpString( $string ) {
                if ( is_array( $string ) || is_object( $string ) ) {
index 1175e9e..968ee15 100644 (file)
@@ -94,6 +94,9 @@ class MssqlUpdater extends DatabaseUpdater {
                                'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
                        [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
                        [ 'addField', 'tag_summary', 'ts_id', 'patch-tag_summary-ts_id.sql' ],
+
+                       // 1.29
+                       [ 'addField', 'externallinks', 'el_index_60', 'patch-externallinks-el_index_60.sql' ],
                ];
        }
 
index a637ce0..d95222c 100644 (file)
@@ -291,6 +291,9 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
                        [ 'addField', 'tag_summary', 'ts_id', 'patch-tag_summary-ts_id.sql' ],
                        [ 'modifyField', 'recentchanges', 'rc_ip', 'patch-rc_ip_modify.sql' ],
+
+                       // 1.29
+                       [ 'addField', 'externallinks', 'el_index_60', 'patch-externallinks-el_index_60.sql' ],
                ];
        }
 
index e1e0d0f..1f0e411 100644 (file)
@@ -119,6 +119,9 @@ class OracleUpdater extends DatabaseUpdater {
                        [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
                        [ 'addField', 'tag_summary', 'ts_id', 'patch-tag_summary-ts_id.sql' ],
 
+                       // 1.29
+                       [ 'addField', 'externallinks', 'el_index_60', 'patch-externallinks-el_index_60.sql' ],
+
                        // KEEP THIS AT THE BOTTOM!!
                        [ 'doRebuildDuplicateFunction' ],
 
index 790fbe7..1eb3f41 100644 (file)
@@ -443,6 +443,11 @@ class PostgresUpdater extends DatabaseUpdater {
                                "INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('change_tag_ct_id_seq')" ],
                        [ 'addPgField', 'tag_summary', 'ts_id',
                                "INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('tag_summary_ts_id_seq')" ],
+
+                       // 1.29
+                       [ 'addPgField', 'externallinks', 'el_index_60', "BYTEA NOT NULL DEFAULT ''" ],
+                       [ 'addPgIndex', 'externallinks', 'el_index_60', '( el_index_60, el_id )' ],
+                       [ 'addPgIndex', 'externallinks', 'el_from_index_60', '( el_from, el_index_60, el_id )' ],
                ];
        }
 
index 388c034..32068e6 100644 (file)
@@ -158,6 +158,9 @@ class SqliteUpdater extends DatabaseUpdater {
                                'patch-add-rc_name_type_patrolled_timestamp_index.sql' ],
                        [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
                        [ 'addField', 'tag_summary', 'ts_id', 'patch-tag_summary-ts_id.sql' ],
+
+                       // 1.29
+                       [ 'addField', 'externallinks', 'el_index_60', 'patch-externallinks-el_index_60.sql' ],
                ];
        }
 
index 6fb8927..84c580f 100644 (file)
@@ -10,7 +10,8 @@
                        "محمد أحمد عبد الفتاح",
                        "Maroen1990",
                        "Super ninja2",
-                       "Zpizza"
+                       "Zpizza",
+                       "ديفيد"
                ]
        },
        "config-desc": "مثبت لميدياويكي",
        "config-env-bad": "جرى التحقق من البيئة. لا يمكنك تنصيب ميدياويكي.",
        "config-env-php": "بي إتش بي $1 مثبت.",
        "config-env-hhvm": "نصبت HHVM $1.",
+       "config-outdated-sqlite": "<strong>تحذير:</strong> لديك SQLite $1, which وهو أقل من الحد الأدنى المطلوب للنسخة $2. SQLite سوف يكون غير متوفر.",
+       "config-xcache": "تثبيت [http://xcache.lighttpd.net/ XCache]",
+       "config-apc": "تثبيت [http://www.php.net/apc APC]",
+       "config-apcu": "تثبيت [http://www.php.net/apcu APCu]",
+       "config-wincache": "تثبيت [http://www.iis.net/download/WinCacheForPhp WinCache]",
+       "config-diff3-bad": "جنو diff3 غير موجود.",
+       "config-imagemagick": "تم العثور على ImageMagick: <code>$1</code>.\nسيتم تمكين تصغير الصور إذا قمت بتمكين التحميل.",
+       "config-no-scaling": "لا يمكن أن تجد مكتبة GD أو ImageMagick; سيتم تعطيل تصغير الصور.",
+       "config-no-uri": "<strong>خطأ:</strong>  لا يمكن أن تحدد URI الحالي.تم  إحباط التثبيت.",
+       "config-using-server": "باستخدام اسم الخادم \"<nowiki>$1</nowiki\".",
+       "config-using-uri": "باستخدام URL الخادم \"<nowiki>$1$2</nowiki>\".",
        "config-db-type": "نوع قاعدة البيانات:",
        "config-db-host": "مضيف قاعدة البيانات:",
+       "config-db-host-oracle": "قاعدة بيانات TNS:",
        "config-db-wiki-settings": "حدِّد هذا الويكي",
        "config-db-name": "اسم قاعدة البيانات",
+       "config-db-name-help": "اختر الاسم الذي يعرف الويكي الخاص بك. لا يجب أن يحتوي على مسافات. إذا كنت تستخدم استضافة المواقع المشتركة، مزود الاستضافة إما سيعطيك اسم قاعدة بيانات محددة لاستخدامها أو سيتيح لك إنشاء قواعد بيانات عن طريق لوحة التحكم.",
        "config-db-name-oracle": "سكيما قاعدة البيانات:",
        "config-db-install-account": "حساب المستخدم للتنصيب",
        "config-db-username": "اسم مستخدم قاعدة البيانات:",
        "config-db-password": "كلمة سر قاعدة البيانات:",
+       "config-db-install-username": "أدخل اسم المستخدم الذي سيتم استخدامه للاتصال بقاعدة البيانات أثناء عملية التثبيت. هذا ليس اسم مستخدم لحساب ميدياويكي. هذا اسم مستخدم لقاعدة البيانات الخاصة بك.",
+       "config-db-install-password": "أدخل كلمة المرور التي سيتم استخدامها للاتصال بقاعدة البيانات أثناء عملية التثبيت. ليست هذه كلمة مرور لحساب ميدياويكي. هذه كلمة مرور لقاعدة البيانات الخاصة بك.",
+       "config-db-install-help": "أدخل اسم المستخدم وكلمة المرور الذين سيتم استخدامهما للاتصال بقاعدة البيانات أثناء عملية التثبيت.",
+       "config-db-account-lock": "استخدم نفس اسم المستخدم وكلمة المرور أثناء التشغيل العادي",
+       "config-db-wiki-account": "حساب المستخدم للتشغيل العادي",
+       "config-db-wiki-help": "أدخل اسم المستخدم وكلمة المرور التي سيتم استخدامهما للاتصال بقاعدة البيانات أثناء عملية الويكي العادية. في حالة عدم وجود حساب وتثبيت الحساب لديه امتيازات كافية، سيتم إنشاء حساب المستخدم هذا مع الحد الأدنى من الامتيازات المطلوبة لتشغيل الويكي.",
        "config-db-prefix": "بادئة جدول قاعدة البيانات:",
+       "config-db-prefix-help": "إذا كنت بحاجة إلى مشاركة قاعدة بيانات واحدة بين ويكيات متعددة، أو بين ميدياويكي وتطبيق آخر على شبكة الإنترنت، يمكنك الاختيار لإضافة بادئة لجميع أسماء الجداول لتجنب النزاعات. لا تستخدم مسافات. وعادة ما يتم ترك هذا الحقل فارغا.",
+       "config-mysql-old": "MySQL $1 أو لاحق مطلوب.لديك $2.",
        "config-db-port": "منفذ قاعدة البيانات:",
        "config-db-schema": "سكيما لميدياويكي",
+       "config-db-schema-help": "هذا المخطط عادة يكون على ما يرام. غيره إذا كنت تعرف أنك في حاجة إلى هذا فقط.",
+       "config-pg-test-error": "لا يمكن الاتصال بقاعدة البيانات <strong>$1</strong>: $2",
+       "config-sqlite-dir": "دليل بيانات SQLite:",
+       "config-oracle-def-ts": "جدولية افتراضية:",
+       "config-oracle-temp-ts": "جدولية مؤقتة:",
        "config-type-mysql": "MySQL (أو متوافق)",
        "config-type-postgres": "بوستجر إس كيو إل",
        "config-type-sqlite": "إس كيو لايت",
        "config-type-oracle": "أوراكل",
        "config-type-mssql": "خادم SQL لميكروسوفت",
+       "config-support-info": "ميدياويكي يدعم نظم قواعد البيانات التالية: $1 إذا كنت لا ترى نظام قاعدة البيانات الذي تحاول استخدامه مدرجًا أدناه، اتبع الإرشادات المرتبطة فوق لتمكين الدعم.",
        "config-header-mysql": "إعدادات MySQL",
        "config-header-postgres": "إعدادات PostgreSQL",
        "config-header-sqlite": "إعدادات SQLite",
        "config-header-oracle": "إعدادات أوراكل",
+       "config-header-mssql": "إعدادات خادم Microsoft SQL",
        "config-invalid-db-type": "نوع قاعدة بيانات غير صحيح",
+       "config-missing-db-name": "يجب عليك إدخال قيمة ل\"{{int:config-db-name}}\".",
+       "config-missing-db-server-oracle": "يجب عليك إدخال قيمة ل\"{{int:config-db-host-oracle}}\".",
+       "config-connection-error": "$1.\nتحقق من المضيف، واسم المستخدم وكلمة المرور وحاول مرة أخرى.",
+       "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-mkdir-error": "خطأ في إنشاء دليل البيانات \"$1\". تحقق من الموقع وحاول مرة أخرى.",
+       "config-sqlite-connection-error": "1$.\nتحقق من اسم دليل البيانات وقواعد البيانات أدناه وحاول مرة أخرى.",
+       "config-sqlite-readonly": "الملف <code>$1</code> غير قابل للكتابة.",
+       "config-sqlite-cant-create-db": "لا يمكن إنشاء ملف قاعدة البيانات <code>$1</code>.",
+       "config-can-upgrade": "هناك جداول ميدياويكي في قاعدة البيانات هذه. للارتقاء بها إلى ميدياويكي $1; انقر على <strong>متابعة</strong>.",
+       "config-regenerate": "إعادة تكوين LocalSettings.php ←",
+       "config-show-table-status": "<code> إظهار جدول الحالة </code> فشل الاستعلام!",
+       "config-unknown-collation": "<strong>تحذير:</strong> قاعدة بيانات يستخدم ترتيبا غير معروف.",
        "config-db-web-account": "حساب قاعدة البيانات للوصول عبر الوب",
+       "config-db-web-help": "حدد اسم المستخدم وكلمة المرور التي سيستخدمهما خادم الويب للاتصال بخادم قاعدة البيانات، أثناء عملية الويكي العادية.",
        "config-db-web-account-same": "استعمل نفس الحساب للتنصيب",
        "config-db-web-create": "إنشئ حساب إذا لم يكن موجودا بالفعل",
        "config-db-web-no-create-privs": "الحساب الذي حددته لتركيب ليس لديه امتيازات كافية لإنشاء حساب.\nالحساب الذي حددته هنا موجود بالفعل.",
        "config-mysql-binary": "ثنائي",
        "config-mysql-utf8": "يو تي إف-8",
        "config-mssql-auth": "نوع الاستيثاق:",
+       "config-mssql-sqlauth": "مصادقة خادم SQL",
+       "config-mssql-windowsauth": "مصادقة ويندوز",
        "config-site-name": "اسم الويكي:",
        "config-site-name-blank": "أدخل اسم موقع.",
        "config-project-namespace": "نطاق المشروع:",
        "config-ns-site-name": "مثل اسم الويكي: $1",
        "config-ns-other": "أخرى (حدد)",
        "config-ns-other-default": "ماي ويكي",
+       "config-ns-invalid": "النطاق المحدد \"<nowiki>$1</nowiki>\" غير صالح.\nحدد نطاق مشروع مختلف.",
+       "config-ns-conflict": "النطاق المحدد \"<nowiki>$1</ nowiki>\" يتعارض مع نطاق ميدياويكي الافتراضي. حدد نطاق مشروع مختلف.",
        "config-admin-box": "حساب إداري",
        "config-admin-name": "اسم المستخدم:",
        "config-admin-password": "كلمة السر:",
        "config-admin-password-confirm": "كلمة المرور مرة أخرى:",
+       "config-admin-help": "أدخل اسم المستخدم المفضل لديك هنا، على سبيل المثال \"جو أشرف فاروق\". هذا هو الاسم الذي ستستخدمه لتسجيل الدخول إلى الويكي.",
        "config-admin-name-blank": "أدخل اسم مستخدم لإداري.",
+       "config-admin-name-invalid": "اسم المستخدم المحدد \"<nowiki>$1</ nowiki>\" غير صالح. حدد اسم مستخدم مختلفا.",
+       "config-admin-password-blank": "أدخل كلمة مرور حساب الإداري.",
        "config-admin-password-mismatch": "كلمات السر اثنين التي أدخلتها لا تتطابق.",
        "config-admin-email": "عنوان البريد الإلكتروني:",
        "config-admin-email-help": "إدخال عنوان البريد الإلكتروني هنا ليسمح لك لتلقي البريد الإلكتروني من المستخدمين الآخرين على ويكي، إعادة تعيين كلمة المرور الخاصة بك، ويتم إخطار من التغييرات للصفحات في قائمة مراقبتك. يمكنك ترك هذا الحقل فارغا.",
+       "config-admin-error-user": "خطأ داخلي عند إنشاء إداري باسم \"<nowiki>$1</ nowiki>\".",
+       "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-noemail": "حاولت الاشتراك في القائمة البريدية الخاصة بإصدار إعلانات دون تقديم عنوان بريد إلكتروني. يُرجَى إدخال عنوان بريد إلكتروني إذا كنت ترغب في الاشتراك في القائمة البريدية.",
+       "config-pingback": "تبادل البيانات حول هذا التثبيت مع مطوري ميدياويكي.",
+       "config-almost-done": "لقد شارفت على الانتهاء! يمكنك الآن تخطي التكوين المتبقي وتثبيت الويكي الآن.",
        "config-optional-continue": "اسألني المزيد من الأسئلة",
        "config-optional-skip": "إنني أشعر بالملل بالفعل، فقط قم بتثبيت الويكي",
        "config-profile": "ملف صلاحيات المستخدم:",
        "config-license-cc-by-sa": "المشاع الإبداعي النسبة للمؤلف المشاركة بالمثل",
        "config-license-cc-by": "المشاع الإبداعي النسبة للمؤلف",
        "config-license-cc-by-nc-sa": "المشاع الإبداعي النسبة للمؤلف غير تجاري المشاركة بالمثل",
+       "config-license-cc-0": "المشاع الإبداعي صفر (ملكية عامة)",
+       "config-license-gfdl": "رخصة جنو للوثائق الحرة 1.3 أو لاحقة",
        "config-license-pd": "ملكية عامة",
        "config-license-cc-choose": "اختر ترخيص مشاع إبداعي مخصص",
        "config-email-settings": "إعدادات البريد الإلكتروني",
        "config-enable-email": "تمكين البريد الإلكتروني الصادرة",
+       "config-enable-email-help": "إذا كنت تريد إرسال بريد إلكتروني إلى العمل، [http://www.php.net/manual/en/mail.configuration.php إعدات بريد PHP's] تحتاج لأن يتم تكوينها بشكل صحيح. إذا كنت لا تريد أيا من ميزات البريد الإلكتروني، يمكنك تعطيلها هنا.",
        "config-email-user": "تفعيل البريد الإلكتروني من المستخدم إلى مستخدم آخر",
        "config-email-user-help": "يتيح لكل المستخدمين إرسال رسائل بريد إلكتروني إلى بعضهم البعض إذا فعَّلوا هذا الخيار في تفضيلاتهم.",
        "config-email-usertalk": "فعل إخطارات صفحات نقاش المستخدمين",
+       "config-email-usertalk-help": "السماح للمستخدمين بتلقي الإخطارات بشأن تغييرات صفحة نقاش المستخدم، إذا كانوا قد مكنوها في تفضيلاتهم.",
        "config-email-watchlist": "تمكين إشعارات قائمة المراقبة",
+       "config-email-watchlist-help": "السماح للمستخدمين بالحصول على إشعارات حول صفحاتهم المراقبة إذا كانوا قد مكنوها في تفضيلاتهم.",
        "config-email-auth": "تمكين مصادقة البريد الإلكتروني",
        "config-email-sender": "يرجع عنوان البريد الإلكتروني:",
        "config-upload-settings": "الصور وتحميل الملفات",
        "config-upload-deleted": "المجلد للملفات المحذوفة:",
        "config-logo": "مسار الشعار:",
        "config-instantcommons": "تمكين الاستخدام الفوري لويكيميديا كومنز InstantCommons",
+       "config-cc-error": "لم يعطِ منتقي رخصة المشاع الإبداعي أية نتيجة; أدخل اسم الترخيص يدويا.",
        "config-cc-again": "اختر مجددًا",
+       "config-cc-not-chosen": "اختر أي ترخيص تريده ثم اضغط على \"متابعة\".",
        "config-advanced-settings": "ضبط متقدم",
        "config-cache-options": "إعدادات التخزين المؤقت الكائن:",
+       "config-cache-none": "لا يوجد تخزين مؤقت (لم تتم إزالة أية وظيفة، لكن قد تتأثر السرعة على مواقع ويكي أكبر)",
+       "config-cache-accel": "كائن التخزين المؤقت PHP (APC أو APCu أو  XCache أو WinCache)",
        "config-extensions": "امتدادات",
+       "config-extensions-help": "تم الكشف عن الملحقات المذكورة أعلاه في دليل <code>./ملحقاتك</code>، ويمكن أن يتطلب تكوينا إضافيا، ولكن يمكنك تمكينها الآن.",
        "config-skins": "الواجهات",
        "config-skins-use-as-default": "استخدم هذه الواجهة كافتراضية",
+       "config-install-alreadydone": "<strong>تحذير:</strong> يبدو أنك قد قمت بالفعل بتثبيت ميدياويكي وتحاول تثبيته مرة أخرى. الرجاء التوجه إلى الصفحة التالية.",
+       "config-install-begin": "عن طريق الضغط على \"{{int:config-continue}}\"، سوف تبدأ تثبيت ميدياويكي. إذا كنت لا تزال ترغب في إجراء تغييرات، اضغط على \"{{int:config-back}}\".",
        "config-install-step-done": "نفذ",
        "config-install-step-failed": "فشل",
        "config-install-extensions": "متضمنا الامتدادات",
        "config-install-database": "إنشاء قاعدة البيانات",
        "config-install-schema": "إنشاء السكيما",
+       "config-install-pg-schema-not-exist": "مخطط PostgreSQL غير موجود.",
        "config-install-pg-commit": "تنفيذ التغييرات",
+       "config-install-pg-plpgsql": "التحقق من لغة PL/pgSQL",
+       "config-pg-no-plpgsql": "تحتاج إلى تثبيت لغة PL/pgSQL في قاعدة البيانات $1",
+       "config-pg-no-create-privs": "الحساب الذي حددته للتنزيل ليست لديه امتيازات كافية لإنشاء حساب.",
        "config-install-user": "إنشاء مستخدم قاعدة البيانات",
        "config-install-user-alreadyexists": "المستخدم \"$1\" موجود بالفعل",
        "config-install-user-create-failed": "إنشاء مستخدم \"$1\" فشل:$2",
+       "config-install-user-grant-failed": "منح الصلاحية للمستخدم \"$1\" فشل: $2",
        "config-install-user-missing": "المستخدم المحدد \"$1\" غير موجود",
+       "config-install-user-missing-create": "المستخدم المحدد \"$1\" غير موجود. يُرجَى النقر على مربع \"إنشاء حساب\" أدناه إذا كنت تريد إنشاءه.",
        "config-install-tables": "إنشاء الجداول",
+       "config-install-tables-exist": "<strong>تحذير:</strong> يبدو أن جداول ميدياويكي موجودة بالفعل; تخطي الإنشاء.",
+       "config-install-tables-failed": "<strong>خطأ:</strong> فشل إنشاء الجدول بسبب الخطأ التالي: $1",
+       "config-install-interwiki": "ملء جدول الإنترويكي الإفتراضي",
+       "config-install-interwiki-list": "لا يمكن قراءة الملف <code>interwiki.list</code>.",
+       "config-install-interwiki-exists": "<strong>تحذير:</strong> يبدو أن جدول الإنترويكي به إدخالات بالفعل. تخطي القائمة الافتراضي.",
        "config-install-stats": "بدء الإحصاءات",
        "config-install-keys": "توليد المفاتيح السرية",
+       "config-insecure-keys": "<strong>تحذير:</strong> {{PLURAL:$2|مفتاح الأمان|مفاتيح الأمان}} ($1) التي تم إنشاؤها أثناء التثبيت ليست آمنة تماما; جرب تغيير{{PLURAL:$2|ه|هم}} يدويا.",
        "config-install-updates": "منع تشغيل التحديثات غير الضرورية",
+       "config-install-updates-failed": "<strong>خطأ:</strong> إدخال مفاتيح التحديث إلى الجداول فشلت بسبب الخطأ التالي: $1",
        "config-install-sysop": "إنشاء حساب مستخدم إداري",
+       "config-install-subscribe-fail": "غير قادر على الاشتراك في ميدياويكي-إعلان: $1",
+       "config-install-subscribe-notpossible": "لم يتم تثبيت cURL و <code>allow_url_fopen</code> غير متوفر.",
        "config-install-mainpage": "إنشاء صفحة رئيسية بالمحتوى الافتراضي",
        "config-install-extension-tables": "إنشاء جداول للامتدادات المفعلة",
        "config-install-mainpage-failed": "لم يتمكن من إدراج الصفحة الرئيسية: $1",
index 4398492..6b7372c 100644 (file)
        "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. ([http://www.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. Pueden haber algunos fallos menores destacables, y no es recomendable para su uso en un entorno de producción. ([http://www.php.net/manual/es/pgsql.installation.php Cómo compilar PHP con compatibilidad PostgreSQL]).",
+       "config-dbsupport-postgres": "[{{int:version-db-postgres-url}} PostgreSQL] es un sistema de base de datos popular de código abierto, alternativa a MySQL. ([http://www.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-mssql": "* [{{int:version-db-mssql-url}} Microsoft SQL Server] es una base de datos comercial a nivel empresarial para Windows. ([http://www.php.net/manual/en/sqlsrv.installation.php Cómo compilar PHP con soporte para SQLSRV])",
        "config-nofile": "El archivo \"$1\" no se pudo encontrar. ¿Se ha eliminado?",
        "config-extension-link": "¿Sabías que tu wiki admite [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Extensions extensiones]?\n\nPuedes navegar por las [https://www.mediawiki.org/wiki/Special:MyLanguage/Category:Extensions_by_category categorías] o visitar el [https://www.mediawiki.org/wiki/Extension_Matrix centro de extensiones] para ver una lista completa.",
        "mainpagetext": "<strong>MediaWiki se ha instalado.</strong>",
-       "mainpagedocfooter": "Consulta la [https://meta.wikimedia.org/wiki/Help:Contents/es guía del usuario] para obtener información sobre el uso del software wiki.\n\n== Primeros pasos ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista de ajustes de configuración]\n* [https://www.mediawiki.org/wiki/Manual:FAQ/es Preguntas frecuentes sobre MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo de anuncios de publicación de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Traducir MediaWiki en tu idioma]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Aprende cómo combatir el spam en tu wiki]"
+       "mainpagedocfooter": "Consulta la [https://meta.wikimedia.org/wiki/Special:MyLanguage/Help:Contents guía] para obtener información sobre el uso del software wiki.\n\n== Primeros pasos ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Lista de ajustes de configuración]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ Preguntas frecuentes sobre MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Lista de correo de anuncios de publicación de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Traducir MediaWiki a tu idioma]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Aprende a combatir el spam en tu wiki]"
 }
index d1ba15a..6e632d6 100644 (file)
@@ -54,7 +54,7 @@
        "config-help-restart": "آیا می‌خواهید همهٔ اطلاعات ذخیره شده‌ای که وارد کرده‌اید را پاک کنید و دوباره روند نصب را شروع کنید؟",
        "config-restart": "بله، دوباره شروع کن",
        "config-welcome": "===بررسی‌های محیطی===\nبرای فهمیدن اینکه این محیط برای نصب مدیاویکی مناسب است، اکنون بررسی‌های اساسی انجام خواهد‌شد.\nاگر به دنبال پشتیبانی در چگونگی تکمیل نصب هستید،به یاد داشته باشید این اطلاعات را بگنجانید.",
-       "config-copyright": "=== حق رونوشت و شرایط ===\n\n$1\n\nاین برنامه، نرم‌افزاری آزاد است. می‌توانید تحت شرایط نگارش ۲ یا (بنا به نظر خود) هر نگارش جدیدتری از پروانهٔ جامع همگانی گنو که توسط بنیاد نرم‌افزار آزاد منتشر شده، بازنشرش کرده و/یا تغییرش دهید.\n\n\nاین برنامه با این امید توزیع شده که مفید باشد، ولی <strong>بدون هیچ ضمانتی</strong>، حتا ضمانت ضمنی <strong>معامله‌پذیری</strong> یا <strong>تناسب برای کاربردی خاص </strong>.\n\nبرای جزئیات بیشتر، پروانهٔ جامع همگانی گنو را ببینید.\n\n\nباید همراه این برنامه، <doclink href=Copying>نگارشی از پروانهٔ جامع همگانی گنو</doclink> را گرفته باشید. اگر چنین نیست، با بنیاد نرم‌افزار آزاد به نشانی 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA مکاتبه کرده یا [http://www.gnu.org/copyleft/gpl.html پروانه را برخط بخوانید].",
+       "config-copyright": "=== حق رونوشت و شرایط ===\n\n$1\n\nاین برنامه، نرم‌افزاری آزاد است. می‌توانید تحت شرایط نگارش ۲ یا (بنا به نظر خود) هر نگارش جدیدتری از پروانهٔ جامع همگانی گنو که توسط بنیاد نرم‌افزار آزاد منتشر شده، بازنشرش کرده و/یا تغییرش دهید.\n\n\nاین برنامه با این امید توزیع شده که مفید باشد، ولی <strong>بدون هیچ ضمانتی</strong>، حتا ضمانت ضمنی <strong>معامله‌پذیری</strong> یا <strong>تناسب برای کاربردی خاص </strong>.\n\nبرای جزئیات بیشتر، پروانهٔ جامع همگانی گنو را ببینید.\n\n\nباید همراه این برنامه، <doclink href=Copying>نگارشی از پروانهٔ جامع همگانی گنو</doclink> را گرفته باشید. اگر چنین نیست، با بنیاد نرم‌افزار آزاد به نشانی 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA مکاتبه کرده یا [http://www.gnu.org/copyleft/gpl.html پروانه را برخط بخوانید].",
        "config-sidebar": "* [https://www.mediawiki.org صفحهٔ اصلی مدیاویکی]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents راهنمای کاربر]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents راهنمای مدیر]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ پرسش‌های رایج]\n----\n* <doclink href=Readme>مرا بخوان</doclink>\n* <doclink href=ReleaseNotes>یادداشت‌های انتشار</doclink>\n* <doclink href=Copying>نسخه برداری</doclink>\n* <doclink href=UpgradeDoc>ارتقا</doclink>",
        "config-env-good": "محیط بررسی شده‌است.\nشما می‌توانید مدیاویکی را نصب کنید.",
        "config-env-bad": "محیط بررسی شده‌است.\nشما نمی‌توانید مدیاویکی را نصب کنید.",
        "config-imagemagick": "ایمیج‌مجیک پیدا شد: <code>$1</code>.\nاگر ارسال‌ها را فعال کنید،تصویر کوچک فعال خواهد‌شد.",
        "config-gd": "گرافیک‌های جی‌دی ساخته‌‌ شده در کتابخانه پیدا شد.\nاگر ارسال‌ها را فعال کنید تصویر کوچک فعال خواهد‌شد.",
        "config-no-scaling": "کتابخانهٔ جی‌دی یا ایمیج‌مجیک نتوانست پیدا شود.\nتصویر کوچک غیر‌فعال خواهد‌شد.",
-       "config-no-uri": "'''خطا:''' یوآرآی فعلی را نتوانست مشخص کند.\nنصب نافرجام ماند.",
+       "config-no-uri": "'''خطا:''' یوآرآی فعلی را نتوانست مشخص کند.\nنصب شکست خورد.",
        "config-no-cli-uri": "<strong>هشدار:</strong> هیچ اسکریپت‌پتی تعیین نشده، از پیش‌فرض استفاده کنید:\n<code>$1</code>.",
        "config-using-server": "از اسم سرور \"<nowiki>$1</nowiki>\" استفاده کنید.",
        "config-using-uri": "از اسم سرور \"<nowiki>$1$2</nowiki>\" استفاده کنید.",
        "config-uploads-not-safe": "'''هشدار:''' فهرست پیش‌فرض ارسال‌های <code>$1</code> شما برای اجرای متون دلخواه آسیب‌پذیر است.\nاگرچه مدیاویکی همهٔ پوشه‌های ارسال‌ شده را برای خطرات امنیتی بررسی می‌کند، پیش از فعال‌سازی ارسال‌ها، بسیار به [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security close this security vulnerability] توصیه شده‌است.",
        "config-no-cli-uploads-check": "'''هشدار:''' فهرست پیش‌فرض ارسال‌های شما (<code>$1</code>) برای آسیب‌پذیری اجرای متن دلخواه در طول نصب سی‌ال آی بررسی نشده‌است.",
-       "config-brokenlibxml": "دستگاه شما دارای تلفیقی از نسخه‌های پی‌اچ‌پی و لیبکسمل۲ است که ناقص است و می‌تواند دلیل از بین رفتن اطلاعات مخفی در مدیاویکی و دیگر برنامه‌های کاربردی شبکه باشد.\nارتقاء به لیبکسمل۲  ۲.۷.۳ یا بالاتر ([https://bugs.php.net/bug.php?id=45996 bug filed with PHP]) ارتفاء دهید.\nنصب نافرجام ماند.",
+       "config-brokenlibxml": "دستگاه شما دارای تلفیقی از نسخه‌های پی‌اچ‌پی و لیبکسمل۲ است که ناقص است و می‌تواند دلیل از بین رفتن اطلاعات مخفی در مدیاویکی و دیگر برنامه‌های کاربردی شبکه باشد.\nارتقاء به لیبکسمل۲  ۲.۷.۳ یا بالاتر ([https://bugs.php.net/bug.php?id=45996 bug filed with PHP]) ارتفاء دهید.\nنصب شکست خورد ماند.",
        "config-suhosin-max-value-length": "سوهُسین نصب شده‌است و پارامتر جت <code>length</code> را به $1 بایت محدود می‌کند.\n قسمت بارکنندهٔ منبع مدیاویکی پیرامون این محدوده کار خواهد‌کرد، اما عملکرد آن را پایین می‌آورد. اگر به هیچ وجه ممکن نیست، باید <code>suhosin.get.max_value_length</code> را به ۱۰۲۴ یا بالاتر در <code>php.ini</code> تنظیم کنید، و \n<code>$wgResourceLoaderMaxQueryLength</code> را به مقدار مشابه در <code>LocalSettings.php</code> تنظیم کنید.",
        "config-db-type": "نوع پایگاه اطلاعات:",
        "config-db-host": "میزبان پایگاه اطلاعات:",
index 296ddbd..fe6bb47 100644 (file)
@@ -13,7 +13,8 @@
                        "Bennylin",
                        "WongKentir",
                        "Macofe",
-                       "Rachmat.Wahidi"
+                       "Rachmat.Wahidi",
+                       "Gombang"
                ]
        },
        "config-desc": "Penginstal untuk MediaWiki",
        "config-subscribe": "Berlangganan ke [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce milis pengumuman rilis].",
        "config-subscribe-help": "Ini adalah milis bervolume rendah yang digunakan untuk pengumuman rilis, termasuk pengumuman keamanan penting.\nAnda sebaiknya berlangganan dan memperbarui instalasi MediaWiki saat versi baru keluar.",
        "config-subscribe-noemail": "Anda mencoba untuk berlangganan milis pengumuman rilis tanpa menyediakan alamat email.\nHarap berikan alamat surel jika Anda ingin berlangganan ke milis.",
+       "config-pingback": "Bagikan data tentang instalasi ini dengan pengembang MediaWiki",
        "config-almost-done": "Anda hampir selesai!\nAnda sekarang dapat melewati sisa konfigurasi dan menginstal wiki sekarang.",
        "config-optional-continue": "Berikan saya pertanyaan lagi.",
        "config-optional-skip": "Saya sudah bosan, instal saja wikinya.",
        "config-profile-no-anon": "Pembuatan akun diperlukan",
        "config-profile-fishbowl": "Khusus penyunting terdaftar",
        "config-profile-private": "Wiki pribadi",
-       "config-profile-help": "Wiki paling baik bekerja jika Anda membiarkan sebanyak mungkin orang untuk menyunting. Dengan MediaWiki, sangat mudah meninjau perubahan terbaru dan mengembalikan kerusakan yang dilakukan oleh pengguna naif atau berbahaya.\n\nNamun, berbagai kegunaan lain dari MediaWiki telah ditemukan, dan kadang tidak mudah untuk meyakinkan semua orang manfaat dari cara wiki. Jadi, Anda yang menentukan.\n\n'''{{int:config-profile-wiki}}''' memungkinkan setiap orang untuk menyunting, bahkan tanpa masuk.\n'''{{int:config-profile-no-anon}}''' menyediakan akuntabilitas tambahan, tetapi dapat mencegah kontributor biasa.\n\n'''{{int:config-profile-fishbowl}}''' memungkinkan pengguna yang disetujui untuk menyunting, tetapi publik dapat melihat halaman, termasuk riwayatnya.\n'''{{int:config-profile-private}}''' hanya memungkinkan pengguna yang disetujui untuk melihat dan menyunting halaman.\n\nKonfigurasi hak pengguna yang lebih kompleks tersedia setelah instalasi. Lihat [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights/id entri manual terkait].",
+       "config-profile-help": "Wiki paling baik bekerja jika Anda membiarkan sebanyak mungkin orang untuk menyunting. Dengan MediaWiki, sangat mudah meninjau perubahan terbaru dan mengembalikan kerusakan yang dilakukan oleh pengguna naif atau berbahaya.\n\nNamun, berbagai kegunaan lain dari MediaWiki telah ditemukan, dan kadang tidak mudah untuk meyakinkan semua orang manfaat dari cara wiki. Jadi, Anda yang menentukan.\n\n'''{{int:config-profile-wiki}}''' memungkinkan setiap orang untuk menyunting, bahkan tanpa masuk log.\n'''{{int:config-profile-no-anon}}''' menyediakan akuntabilitas tambahan, tetapi dapat mengurangi semangat kontributor sambil lalu.\n\n'''{{int:config-profile-fishbowl}}''' memungkinkan pengguna yang disetujui untuk menyunting, tetapi publik dapat melihat halaman, termasuk riwayatnya.\n'''{{int:config-profile-private}}''' hanya memungkinkan pengguna yang disetujui untuk melihat dan menyunting halaman.\n\nKonfigurasi hak pengguna yang lebih kompleks tersedia setelah instalasi. Lihat [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:User_rights/id entri manual terkait].",
        "config-license": "Hak cipta dan lisensi:",
        "config-license-none": "Tidak ada lisensi",
        "config-license-cc-by-sa": "Creative Commons Atribusi Berbagi Serupa",
index 5c4b1c3..6dab088 100644 (file)
@@ -21,7 +21,7 @@
        "config-page-welcome": "ذريعات‌وڪي تي ڀلي ڪري آيا!",
        "config-page-dbconnect": "اعدادخاني سان جُڙو",
        "config-page-upgrade": "هاڻوڪي تنصيبڪاريءَ کي سڌاريو",
-       "config-page-dbsettings": "اعدادخاÙ\86Ù\8a Ø¬Ù\88Ù\86 Ø³Ù\8aٽڱس",
+       "config-page-dbsettings": "اعدادخاÙ\86Ù\8a Ø¬Ù\88Ù\86 ØªØ±ØªÙ\8aبÙ\88Ù\86",
        "config-page-name": "نالو",
        "config-page-options": "آپشنس",
        "config-page-install": "تنصيبيو",
index 6a7172a..2cc0d1a 100644 (file)
@@ -61,6 +61,7 @@
        "config-license-pd": "Җәмгыять мирасы",
        "config-logo": "Логотип URL:",
        "config-cc-again": "Кабат сайлагыз...",
+       "config-advanced-settings": "Өстәмә көйләнмәләр",
        "config-extensions": "Киңәйтүләр",
        "config-skins": "Бизәлеш",
        "config-install-step-done": "әзер",
index b977af5..e7f69d3 100644 (file)
        "config-admin-password-mismatch": "兩次輸入的密碼並不相同。",
        "config-admin-email": "電子郵件地址:",
        "config-admin-email-help": "在此輸入的電子郵件信箱可用來接收 Wiki 上其他使用者所傳送的訊息、重設您的密碼與通知監視清單中頁面更動。您可將此欄位留空。",
-       "config-admin-error-user": "建立管理員帳號 \"<nowiki>$1</nowiki>\" 時發內部錯誤。",
-       "config-admin-error-password": "設定管理員 \"<nowiki>$1</nowiki>\" 的密碼時發內部錯誤:<pre>$2</pre>",
+       "config-admin-error-user": "建立管理員帳號 \"<nowiki>$1</nowiki>\" 時發內部錯誤。",
+       "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您應該訂閱它並在 MediaWiki 發佈新版的時候更新系統。",
index 0e107b3..4ccca97 100644 (file)
@@ -187,7 +187,7 @@ class ClassicInterwikiLookup implements InterwikiLookup {
         * @note More logic is explained in DefaultSettings.
         *
         * @param string $prefix Interwiki prefix
-        * @return Interwiki
+        * @return Interwiki|false
         */
        private function getInterwikiCached( $prefix ) {
                $value = $this->getInterwikiCacheEntry( $prefix );
index 990f112..cacccbe 100644 (file)
@@ -46,6 +46,7 @@ class JobRunner implements LoggerAwareInterface {
        const MAX_ALLOWED_LAG = 3; // abort if more than this much DB lag is present
        const LAG_CHECK_PERIOD = 1.0; // check replica DB lag this many seconds
        const ERROR_BACKOFF_TTL = 1; // seconds to back off a queue due to errors
+       const READONLY_BACKOFF_TTL = 30; // seconds to back off a queue due to read-only errors
 
        /**
         * @param callable $debug Optional debug output handler
@@ -190,7 +191,7 @@ class JobRunner implements LoggerAwareInterface {
 
                                // Back off of certain jobs for a while (for throttling and for errors)
                                if ( $info['status'] === false && mt_rand( 0, 49 ) == 0 ) {
-                                       $ttw = max( $ttw, self::ERROR_BACKOFF_TTL ); // too many errors
+                                       $ttw = max( $ttw, $this->getErrorBackoffTTL( $info['error'] ) );
                                        $backoffDeltas[$jType] = isset( $backoffDeltas[$jType] )
                                                ? $backoffDeltas[$jType] + $ttw
                                                : $ttw;
@@ -253,6 +254,16 @@ class JobRunner implements LoggerAwareInterface {
                return $response;
        }
 
+       /**
+        * @param string $error
+        * @return int TTL in seconds
+        */
+       private function getErrorBackoffTTL( $error ) {
+               return strpos( $error, 'DBReadOnlyError' ) !== false
+                       ? self::READONLY_BACKOFF_TTL
+                       : self::ERROR_BACKOFF_TTL;
+       }
+
        /**
         * @param Job $job
         * @param LBFactory $lbFactory
index 6ae8837..d9457c6 100644 (file)
@@ -126,7 +126,7 @@ class JobQueueAggregatorRedis extends JobQueueAggregator {
 
        /**
         * @param string $name
-        * @return string
+        * @return string[]
         */
        private function decodeQueueName( $name ) {
                list( $type, $wiki ) = explode( '/', $name, 2 );
index 3b34d9b..d4abdc8 100644 (file)
@@ -40,7 +40,7 @@ class ExplodeIterator implements Iterator {
        // The position after the end of the next delimiter
        private $endPos;
 
-       // The current token
+       /** @var string|false The current token */
        private $current;
 
        /**
index 70ce31d..4ddb813 100644 (file)
@@ -32,7 +32,7 @@ class HashRing {
        /** @var Array (location => (start, end)) */
        protected $ring = [];
 
-       /** @var Array (location => (start, end)) */
+       /** @var HashRing|null */
        protected $liveRing;
        /** @var Array (location => UNIX timestamp) */
        protected $ejectionExpiries = [];
index 6b10c09..26f3c4a 100644 (file)
@@ -54,6 +54,59 @@ class StringUtils {
                        ( $newPHP || preg_match( "/\xf4[\x90-\xbf]|[\xf5-\xff]/S", $value ) === 0 );
        }
 
+       /**
+        * Explode a string, but ignore any instances of the separator inside
+        * the given start and end delimiters, which may optionally nest.
+        * The delimiters are literal strings, not regular expressions.
+        * @param string $startDelim Start delimiter
+        * @param string $endDelim End delimiter
+        * @param string $separator Separator string for the explode.
+        * @param string $subject Subject string to explode.
+        * @param bool $nested True iff the delimiters are allowed to nest.
+        * @return ArrayIterator
+        */
+       static function delimiterExplode( $startDelim, $endDelim, $separator,
+               $subject, $nested = false ) {
+               $inputPos = 0;
+               $lastPos = 0;
+               $depth = 0;
+               $encStart = preg_quote( $startDelim, '!' );
+               $encEnd = preg_quote( $endDelim, '!' );
+               $encSep = preg_quote( $separator, '!' );
+               $len = strlen( $subject );
+               $m = [];
+               $exploded = [];
+               while (
+                       $inputPos < $len &&
+                       preg_match(
+                               "!$encStart|$encEnd|$encSep!S", $subject, $m,
+                               PREG_OFFSET_CAPTURE, $inputPos
+                       )
+               ) {
+                       $match = $m[0][0];
+                       $matchPos = $m[0][1];
+                       $inputPos = $matchPos + strlen( $match );
+                       if ( $match === $separator ) {
+                               if ( $depth === 0 ) {
+                                       $exploded[] = substr(
+                                               $subject, $lastPos, $matchPos - $lastPos
+                                       );
+                                       $lastPos = $inputPos;
+                               }
+                       } elseif ( $match === $startDelim ) {
+                               if ( $depth === 0 || $nested ) {
+                                       $depth++;
+                               }
+                       } else {
+                               $depth--;
+                       }
+               }
+               $exploded[] = substr( $subject, $lastPos );
+               // This method could be rewritten in the future to avoid creating an
+               // intermediate array, since the return type is just an iterator.
+               return new ArrayIterator( $exploded );
+       }
+
        /**
         * Perform an operation equivalent to `preg_replace()`
         *
index bd2ce5d..a7ceab2 100644 (file)
@@ -729,7 +729,7 @@ abstract class FileBackendStore extends FileBackend {
        /**
         * @see FileBackendStore::getFileXAttributes()
         * @param array $params
-        * @return bool|string
+        * @return array[][]
         */
        protected function doGetFileXAttributes( array $params ) {
                return [ 'headers' => [], 'metadata' => [] ]; // not supported
index 08cb388..d40e896 100644 (file)
@@ -1701,7 +1701,7 @@ class SwiftFileBackend extends FileBackendStore {
         * @param array $creds From getAuthentication()
         * @param string $container
         * @param string $object
-        * @return array
+        * @return string
         */
        protected function storageUrl( array $creds, $container = null, $object = null ) {
                $parts = [ $creds['storage_url'] ];
index bee34dc..c629e7d 100644 (file)
@@ -34,7 +34,7 @@ use Wikimedia\WaitConditionLoop;
  *
  * Locks on resource keys can either be shared or exclusive.
  *
- * Implementations must keep track of what is locked by this proccess
+ * Implementations must keep track of what is locked by this process
  * in-memory and support nested locking calls (using reference counting).
  * At least LOCK_UW and LOCK_EX must be implemented. LOCK_SH can be a no-op.
  * Locks should either be non-blocking or have low wait timeouts.
@@ -170,7 +170,7 @@ abstract class LockManager {
        /**
         * Get the base 36 SHA-1 of a string, padded to 31 digits.
         * Before hashing, the path will be prefixed with the domain ID.
-        * This should be used interally for lock key or file names.
+        * This should be used internally for lock key or file names.
         *
         * @param string $path
         * @return string
@@ -182,7 +182,7 @@ abstract class LockManager {
        /**
         * Get the base 16 SHA-1 of a string, padded to 31 digits.
         * Before hashing, the path will be prefixed with the domain ID.
-        * This should be used interally for lock key or file names.
+        * This should be used internally for lock key or file names.
         *
         * @param string $path
         * @return string
index 20198bf..b268b9f 100644 (file)
 class DBConnRef implements IDatabase {
        /** @var ILoadBalancer */
        private $lb;
-
-       /** @var IDatabase|null Live connection handle */
+       /** @var Database|null Live connection handle */
        private $conn;
-
        /** @var array|null N-tuple of (server index, group, DatabaseDomain|string) */
        private $params;
 
@@ -22,12 +20,12 @@ class DBConnRef implements IDatabase {
        const FLD_DOMAIN = 2;
 
        /**
-        * @param ILoadBalancer $lb
-        * @param IDatabase|array $conn Connection or (server index, group, DatabaseDomain|string)
+        * @param ILoadBalancer $lb Connection manager for $conn
+        * @param Database|array $conn New connection handle or (server index, query groups, domain)
         */
        public function __construct( ILoadBalancer $lb, $conn ) {
                $this->lb = $lb;
-               if ( $conn instanceof IDatabase ) {
+               if ( $conn instanceof Database ) {
                        $this->conn = $conn; // live handle
                } elseif ( count( $conn ) >= 3 && $conn[self::FLD_DOMAIN] !== false ) {
                        $this->params = $conn;
@@ -595,7 +593,7 @@ class DBConnRef implements IDatabase {
         * Clean up the connection when out of scope
         */
        function __destruct() {
-               if ( $this->conn !== null ) {
+               if ( $this->conn ) {
                        $this->lb->reuseConnection( $this->conn );
                }
        }
index 3d35d76..b9beac8 100644 (file)
@@ -2862,23 +2862,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                return $this->mTrxLevel && ( $this->mTrxAtomicLevels || !$this->mTrxAutomatic );
        }
 
-       /**
-        * Creates a new table with structure copied from existing table
-        * Note that unlike most database abstraction functions, this function does not
-        * automatically append database prefix, because it works at a lower
-        * abstraction level.
-        * The table names passed to this function shall not be quoted (this
-        * function calls addIdentifierQuotes when needed).
-        *
-        * @param string $oldName Name of table whose structure should be copied
-        * @param string $newName Name of table to be created
-        * @param bool $temporary Whether the new table should be temporary
-        * @param string $fname Calling function name
-        * @throws RuntimeException
-        * @return bool True if operation was successful
-        */
-       public function duplicateTableStructure( $oldName, $newName, $temporary = false,
-               $fname = __METHOD__
+       public function duplicateTableStructure(
+               $oldName, $newName, $temporary = false, $fname = __METHOD__
        ) {
                throw new RuntimeException( __METHOD__ . ' is not implemented in descendant class' );
        }
index a06aad2..a4b2df0 100644 (file)
@@ -665,7 +665,7 @@ class DatabaseSqlite extends Database {
        }
 
        /**
-        * @param string $sqls
+        * @param string[] $sqls
         * @param bool $all Whether to "UNION ALL" or not
         * @return string
         */
index 8395359..43cec28 100644 (file)
@@ -186,4 +186,23 @@ interface IMaintainableDatabase extends IDatabase {
         * @return array
         */
        public function listViews( $prefix = null, $fname = __METHOD__ );
+
+       /**
+        * Creates a new table with structure copied from existing table
+        *
+        * Note that unlike most database abstraction functions, this function does not
+        * automatically append database prefix, because it works at a lower abstraction level.
+        * The table names passed to this function shall not be quoted (this function calls
+        * addIdentifierQuotes() when needed).
+        *
+        * @param string $oldName Name of table whose structure should be copied
+        * @param string $newName Name of table to be created
+        * @param bool $temporary Whether the new table should be temporary
+        * @param string $fname Calling function name
+        * @return bool True if operation was successful
+        * @throws RuntimeException
+        */
+       public function duplicateTableStructure(
+               $oldName, $newName, $temporary = false, $fname = __METHOD__
+       );
 }
diff --git a/includes/libs/rdbms/database/MaintainableDBConnRef.php b/includes/libs/rdbms/database/MaintainableDBConnRef.php
new file mode 100644 (file)
index 0000000..fa3ddf9
--- /dev/null
@@ -0,0 +1,68 @@
+<?php
+/**
+ * Helper class to handle automatically marking connections as reusable (via RAII pattern)
+ * as well handling deferring the actual network connection until the handle is used
+ *
+ * @note: proxy methods are defined explicity to avoid interface errors
+ * @ingroup Database
+ * @since 1.29
+ */
+class MaintainableDBConnRef extends DBConnRef implements IMaintainableDatabase {
+       public function tableName( $name, $format = 'quoted' ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function tableNames() {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function tableNamesN() {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function sourceFile(
+               $filename,
+               callable $lineCallback = null,
+               callable $resultCallback = null,
+               $fname = false,
+               callable $inputCallback = null
+       ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function sourceStream(
+               $fp,
+               callable $lineCallback = null,
+               callable $resultCallback = null,
+               $fname = __METHOD__,
+               callable $inputCallback = null
+       ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function dropTable( $tableName, $fName = __METHOD__ ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function deadlockLoop() {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function listViews( $prefix = null, $fname = __METHOD__ ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function textFieldSize( $table, $field ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function streamStatementEnd( &$sql, &$newLine ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+
+       public function duplicateTableStructure(
+               $oldName, $newName, $temporary = false, $fname = __METHOD__
+       ) {
+               return $this->__call( __FUNCTION__, func_get_args() );
+       }
+}
index 9e10884..7d303b1 100644 (file)
@@ -26,7 +26,7 @@
  * @ingroup Database
  * @since 1.23
  */
-class DBExpectedError extends DBError implements MessageSpecifier {
+class DBExpectedError extends DBError implements MessageSpecifier, ILocalizedException {
        /** @var string[] Message parameters */
        protected $params;
 
@@ -42,4 +42,12 @@ class DBExpectedError extends DBError implements MessageSpecifier {
        public function getParams() {
                return $this->params;
        }
+
+       /**
+        * @inheritdoc
+        * @since 1.29
+        */
+       public function getMessageObject() {
+               return Message::newFromSpecifier( $this );
+       }
 }
index 8854479..fc306b4 100644 (file)
@@ -108,8 +108,9 @@ interface ILoadBalancer {
 
        /**
         * Get the index of the reader connection, which may be a replica DB
+        *
         * This takes into account load ratios and lag times. It should
-        * always return a consistent index during a given invocation
+        * always return a consistent index during a given invocation.
         *
         * Side effect: opens connections to databases
         * @param string|bool $group Query group, or false for the generic reader
@@ -121,8 +122,10 @@ interface ILoadBalancer {
 
        /**
         * Set the master wait position
-        * If a DB_REPLICA connection has been opened already, waits
-        * Otherwise sets a variable telling it to wait if such a connection is opened
+        *
+        * If a DB_REPLICA connection has been opened already, then wait immediately.
+        * Otherwise sets a variable telling it to wait if such a connection is opened.
+        *
         * @param DBMasterPos $pos
         */
        public function waitFor( $pos );
@@ -140,6 +143,7 @@ interface ILoadBalancer {
 
        /**
         * Set the master wait position and wait for ALL replica DBs to catch up to it
+        *
         * @param DBMasterPos $pos
         * @param int $timeout Max seconds to wait; default is mWaitTimeout
         * @return bool Success (able to connect and no timeouts reached)
@@ -148,30 +152,29 @@ interface ILoadBalancer {
 
        /**
         * Get any open connection to a given server index, local or foreign
-        * Returns false if there is no connection open
         *
-        * @param int $i Server index
-        * @return IDatabase|bool False on failure
+        * @param int $i Server index or DB_MASTER/DB_REPLICA
+        * @return Database|bool False if no such connection is open
         */
        public function getAnyOpenConnection( $i );
 
        /**
         * Get a connection by index
-        * This is the main entry point for this class.
         *
-        * @param int $i Server index
+        * @param int $i Server index or DB_MASTER/DB_REPLICA
         * @param array|string|bool $groups Query group(s), or false for the generic reader
         * @param string|bool $domain Domain ID, or false for the current domain
         *
         * @throws DBError
-        * @return IDatabase
+        * @return Database
         */
        public function getConnection( $i, $groups = [], $domain = false );
 
        /**
-        * Mark a foreign connection as being available for reuse under a different
-        * DB name or prefix. This mechanism is reference-counted, and must be called
-        * the same number of times as getConnection() to work.
+        * Mark a foreign connection as being available for reuse under a different DB domain
+        *
+        * This mechanism is reference-counted, and must be called the same number of times
+        * as getConnection() to work.
         *
         * @param IDatabase $conn
         * @throws InvalidArgumentException
@@ -181,30 +184,44 @@ interface ILoadBalancer {
        /**
         * Get a database connection handle reference
         *
-        * The handle's methods wrap simply wrap those of a IDatabase handle
+        * The handle's methods simply wrap those of a Database handle
         *
-        * @see LoadBalancer::getConnection() for parameter information
+        * @see ILoadBalancer::getConnection() for parameter information
         *
-        * @param int $db
+        * @param int $i Server index or DB_MASTER/DB_REPLICA
         * @param array|string|bool $groups Query group(s), or false for the generic reader
         * @param string|bool $domain Domain ID, or false for the current domain
         * @return DBConnRef
         */
-       public function getConnectionRef( $db, $groups = [], $domain = false );
+       public function getConnectionRef( $i, $groups = [], $domain = false );
 
        /**
         * Get a database connection handle reference without connecting yet
         *
-        * The handle's methods wrap simply wrap those of a IDatabase handle
+        * The handle's methods simply wrap those of a Database handle
         *
-        * @see LoadBalancer::getConnection() for parameter information
+        * @see ILoadBalancer::getConnection() for parameter information
         *
-        * @param int $db
+        * @param int $i Server index or DB_MASTER/DB_REPLICA
         * @param array|string|bool $groups Query group(s), or false for the generic reader
         * @param string|bool $domain Domain ID, or false for the current domain
         * @return DBConnRef
         */
-       public function getLazyConnectionRef( $db, $groups = [], $domain = false );
+       public function getLazyConnectionRef( $i, $groups = [], $domain = false );
+
+       /**
+        * Get a maintenance database connection handle reference for migrations and schema changes
+        *
+        * The handle's methods simply wrap those of a Database handle
+        *
+        * @see ILoadBalancer::getConnection() for parameter information
+        *
+        * @param int $db Server index or DB_MASTER/DB_REPLICA
+        * @param array|string|bool $groups Query group(s), or false for the generic reader
+        * @param string|bool $domain Domain ID, or false for the current domain
+        * @return MaintainableDBConnRef
+        */
+       public function getMaintenanceConnectionRef( $db, $groups = [], $domain = false );
 
        /**
         * Open a connection to the server given by the specified index
@@ -216,9 +233,9 @@ interface ILoadBalancer {
         *
         * @note If disable() was called on this LoadBalancer, this method will throw a DBAccessError.
         *
-        * @param int $i Server index
+        * @param int $i Server index or DB_MASTER/DB_REPLICA
         * @param string|bool $domain Domain ID, or false for the current domain
-        * @return IDatabase|bool Returns false on errors
+        * @return Database|bool Returns false on errors
         * @throws DBAccessError
         */
        public function openConnection( $i, $domain = false );
index 634993a..14d049c 100644 (file)
@@ -31,7 +31,7 @@ use Wikimedia\ScopedCallback;
 class LoadBalancer implements ILoadBalancer {
        /** @var array[] Map of (server index => server config array) */
        private $mServers;
-       /** @var IDatabase[][] Map of (local/foreignUsed/foreignFree => server index => IDatabase array) */
+       /** @var IDatabase[][][] Map of local/foreignUsed/foreignFree => server index => IDatabase array */
        private $mConns;
        /** @var float[] Map of (server index => weight) */
        private $mLoads;
@@ -441,12 +441,15 @@ class LoadBalancer implements ILoadBalancer {
 
        /**
         * @param int $i
-        * @return IDatabase
+        * @return IDatabase|bool
         */
        public function getAnyOpenConnection( $i ) {
                foreach ( $this->mConns as $connsByServer ) {
                        if ( !empty( $connsByServer[$i] ) ) {
-                               return reset( $connsByServer[$i] );
+                               /** @var $serverConns IDatabase[] */
+                               $serverConns = $connsByServer[$i];
+
+                               return reset( $serverConns );
                        }
                }
 
@@ -657,6 +660,12 @@ class LoadBalancer implements ILoadBalancer {
                return new DBConnRef( $this, [ $db, $groups, $domain ] );
        }
 
+       public function getMaintenanceConnectionRef( $db, $groups = [], $domain = false ) {
+               $domain = ( $domain !== false ) ? $domain : $this->localDomain;
+
+               return new MaintainableDBConnRef( $this, $this->getConnection( $db, $groups, $domain ) );
+       }
+
        /**
         * @see ILoadBalancer::openConnection()
         *
index d12af7a..a657a33 100644 (file)
@@ -491,7 +491,7 @@ class XMPReader implements LoggerAwareInterface {
         * <exif:DigitalZoomRatio>0/10</exif:DigitalZoomRatio>
         * and are processing the 0/10 bit.
         *
-        * @param XMLParser $parser XMLParser reference to the xml parser
+        * @param resource $parser XMLParser reference to the xml parser
         * @param string $data Character data
         * @throws RuntimeException On invalid data
         */
@@ -776,7 +776,7 @@ class XMPReader implements LoggerAwareInterface {
         * Ignores the outer wrapping elements that are optional in
         * xmp and have no meaning.
         *
-        * @param XMLParser $parser
+        * @param resource $parser
         * @param string $elm Namespace . ' ' . element name
         * @throws RuntimeException
         */
@@ -1188,7 +1188,7 @@ class XMPReader implements LoggerAwareInterface {
         * Generally just calls a helper based on what MODE we're in.
         * Also does some initial set up for the wrapper element
         *
-        * @param XMLParser $parser
+        * @param resource $parser
         * @param string $elm Namespace "<space>" element
         * @param array $attribs Attribute name => value
         * @throws RuntimeException
index 21864ee..c9f1345 100644 (file)
@@ -428,7 +428,7 @@ class ManualLogEntry extends LogEntryBase {
        /** @var int ID of the log entry */
        protected $id;
 
-       /** @var Can this log entry be patrolled? */
+       /** @var bool Can this log entry be patrolled? */
        protected $isPatrollable = false;
 
        /** @var bool Whether this is a legacy log entry */
index c8e9999..21effa0 100644 (file)
@@ -268,7 +268,14 @@ class UserMailer {
                // Add the envelope sender address using the -f command line option when PHP mail() is used.
                // Will default to the $from->address when the UserMailerChangeReturnPath hook fails and the
                // generated VERP address when the hook runs effectively.
-               $extraParams .= ' -f ' . $returnPath;
+
+               // PHP runs this through escapeshellcmd(). However that's not sufficient
+               // escaping (e.g. due to spaces). MediaWiki's email sanitizer should generally
+               // be good enough, but just in case, put in double quotes, and remove any
+               // double quotes present (" is not allowed in emails, so should have no
+               // effect, although this might cause apostrophees to be double escaped)
+               $returnPathCLI = '"' . str_replace( '"', '', $returnPath ) . '"';
+               $extraParams .= ' -f ' . $returnPathCLI;
 
                $headers['Return-Path'] = $returnPath;
 
index 0bb47ba..45540b5 100644 (file)
@@ -1151,22 +1151,8 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
-                       // @todo move this logic to MessageCache
-                       if ( $this->exists() ) {
-                               // NOTE: use transclusion text for messages.
-                               //       This is consistent with  MessageCache::getMsgFromNamespace()
-
-                               $content = $this->getContent();
-                               $text = $content === null ? null : $content->getWikitextForTransclusion();
-
-                               if ( $text === null ) {
-                                       $text = false;
-                               }
-                       } else {
-                               $text = false;
-                       }
-
-                       MessageCache::singleton()->replace( $this->mTitle->getDBkey(), $text );
+                       $messageCache = MessageCache::singleton();
+                       $messageCache->updateMessageOverride( $this->mTitle, $this->getContent() );
                }
 
                return true;
@@ -1405,7 +1391,7 @@ class WikiPage implements Page, IDBAccessObject {
        }
 
        /**
-        * @param string|number|null|bool $sectionId Section identifier as a number or string
+        * @param string|int|null|bool $sectionId Section identifier as a number or string
         * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole page
         * or 'new' for a new section.
         * @param Content $sectionContent New content of the section.
@@ -1445,7 +1431,7 @@ class WikiPage implements Page, IDBAccessObject {
        }
 
        /**
-        * @param string|number|null|bool $sectionId Section identifier as a number or string
+        * @param string|int|null|bool $sectionId Section identifier as a number or string
         * (e.g. 0, 1 or 'T-1'), null/false or an empty string for the whole page
         * or 'new' for a new section.
         * @param Content $sectionContent New content of the section.
@@ -1612,6 +1598,7 @@ class WikiPage implements Page, IDBAccessObject {
         * @param array|null $tags Change tags to apply to this edit
         * Callers are responsible for permission checks
         * (with ChangeTags::canAddTagsAccompanyingChange)
+        * @param Int $undidRevId Id of revision that was undone or 0
         *
         * @throws MWException
         * @return Status Possible errors:
@@ -1633,7 +1620,7 @@ class WikiPage implements Page, IDBAccessObject {
         */
        public function doEditContent(
                Content $content, $summary, $flags = 0, $baseRevId = false,
-               User $user = null, $serialFormat = null, $tags = []
+               User $user = null, $serialFormat = null, $tags = [], $undidRevId = 0
        ) {
                global $wgUser, $wgUseAutomaticEditSummaries;
 
@@ -1712,7 +1699,8 @@ class WikiPage implements Page, IDBAccessObject {
                        'oldId' => $this->getLatest(),
                        'oldIsRedirect' => $this->isRedirect(),
                        'oldCountable' => $this->isCountable(),
-                       'tags' => ( $tags !== null ) ? (array)$tags : []
+                       'tags' => ( $tags !== null ) ? (array)$tags : [],
+                       'undidRevId' => $undidRevId
                ];
 
                // Actually create the revision and create/update the page
@@ -1892,7 +1880,8 @@ class WikiPage implements Page, IDBAccessObject {
                                        );
                                        // Trigger post-save hook
                                        $params = [ &$this, &$user, $content, $summary, $flags & EDIT_MINOR,
-                                               null, null, &$flags, $revision, &$status, $meta['baseRevId'] ];
+                                               null, null, &$flags, $revision, &$status, $meta['baseRevId'],
+                                               $meta['undidRevId'] ];
                                        ContentHandler::runLegacyHooks( 'ArticleSaveComplete', $params );
                                        Hooks::run( 'PageContentSaveComplete', $params );
                                }
@@ -2212,7 +2201,7 @@ class WikiPage implements Page, IDBAccessObject {
         *   - 'no-change': don't update the article count, ever
         */
        public function doEditUpdates( Revision $revision, User $user, array $options = [] ) {
-               global $wgRCWatchCategoryMembership, $wgContLang;
+               global $wgRCWatchCategoryMembership;
 
                $options += [
                        'changed' => true,
@@ -2350,17 +2339,7 @@ class WikiPage implements Page, IDBAccessObject {
                }
 
                if ( $this->mTitle->getNamespace() == NS_MEDIAWIKI ) {
-                       // XXX: could skip pseudo-messages like js/css here, based on content model.
-                       $msgtext = $content ? $content->getWikitextForTransclusion() : null;
-                       if ( $msgtext === false || $msgtext === null ) {
-                               $msgtext = '';
-                       }
-
-                       MessageCache::singleton()->replace( $shortTitle, $msgtext );
-
-                       if ( $wgContLang->hasVariants() ) {
-                               $wgContLang->updateConversionTable( $this->mTitle );
-                       }
+                       MessageCache::singleton()->updateMessageOverride( $this->mTitle, $content );
                }
 
                if ( $options['created'] ) {
@@ -3358,8 +3337,6 @@ class WikiPage implements Page, IDBAccessObject {
         * @param Title $title
         */
        public static function onArticleDelete( Title $title ) {
-               global $wgContLang;
-
                // Update existence markers on article/talk tabs...
                $other = $title->getOtherPage();
 
@@ -3376,11 +3353,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                // Messages
                if ( $title->getNamespace() == NS_MEDIAWIKI ) {
-                       MessageCache::singleton()->replace( $title->getDBkey(), false );
-
-                       if ( $wgContLang->hasVariants() ) {
-                               $wgContLang->updateConversionTable( $title );
-                       }
+                       MessageCache::singleton()->updateMessageOverride( $title, null );
                }
 
                // Images
index f2fca68..770c1c6 100644 (file)
@@ -336,7 +336,7 @@ abstract class TablePager extends IndexPager {
        /**
         * Get a "<select>" element which has options for each of the allowed limits
         *
-        * @param string $attribs Extra attributes to set
+        * @param string[] $attribs Extra attributes to set
         * @return string HTML fragment
         */
        public function getLimitSelect( $attribs = [] ) {
index 4c82dda..6aa3acc 100644 (file)
@@ -276,7 +276,7 @@ class CoreParserFunctions {
                }
                if ( !is_null( $title ) ) {
                        # Convert NS_MEDIA -> NS_FILE
-                       if ( $title->getNamespace() == NS_MEDIA ) {
+                       if ( $title->inNamespace( NS_MEDIA ) ) {
                                $title = Title::makeTitle( NS_FILE, $title->getDBkey() );
                        }
                        if ( !is_null( $arg ) ) {
@@ -341,7 +341,7 @@ class CoreParserFunctions {
                // allow prefix.
                $title = Title::newFromText( $username );
 
-               if ( $title && $title->getNamespace() == NS_USER ) {
+               if ( $title && $title->inNamespace( NS_USER ) ) {
                        $username = $title->getText();
                }
 
@@ -489,40 +489,66 @@ class CoreParserFunctions {
                return $mwObject->matchStartToEnd( $value );
        }
 
-       public static function formatRaw( $num, $raw ) {
+       /**
+        * Formats a number according to a language.
+        *
+        * @param int|float $num
+        * @param string $raw
+        * @param Language|StubUserLang $language
+        * @return string
+        */
+       public static function formatRaw( $num, $raw, $language ) {
                if ( self::matchAgainstMagicword( 'rawsuffix', $raw ) ) {
                        return $num;
                } else {
-                       global $wgContLang;
-                       return $wgContLang->formatNum( $num );
+                       return $language->formatNum( $num );
                }
        }
+
        public static function numberofpages( $parser, $raw = null ) {
-               return self::formatRaw( SiteStats::pages(), $raw );
+               return self::formatRaw( SiteStats::pages(), $raw, $parser->getFunctionLang() );
        }
+
        public static function numberofusers( $parser, $raw = null ) {
-               return self::formatRaw( SiteStats::users(), $raw );
+               return self::formatRaw( SiteStats::users(), $raw, $parser->getFunctionLang() );
        }
        public static function numberofactiveusers( $parser, $raw = null ) {
-               return self::formatRaw( SiteStats::activeUsers(), $raw );
+               return self::formatRaw( SiteStats::activeUsers(), $raw, $parser->getFunctionLang() );
        }
+
        public static function numberofarticles( $parser, $raw = null ) {
-               return self::formatRaw( SiteStats::articles(), $raw );
+               return self::formatRaw( SiteStats::articles(), $raw, $parser->getFunctionLang() );
        }
+
        public static function numberoffiles( $parser, $raw = null ) {
-               return self::formatRaw( SiteStats::images(), $raw );
+               return self::formatRaw( SiteStats::images(), $raw, $parser->getFunctionLang() );
        }
+
        public static function numberofadmins( $parser, $raw = null ) {
-               return self::formatRaw( SiteStats::numberingroup( 'sysop' ), $raw );
+               return self::formatRaw(
+                       SiteStats::numberingroup( 'sysop' ),
+                       $raw,
+                       $parser->getFunctionLang()
+               );
        }
+
        public static function numberofedits( $parser, $raw = null ) {
-               return self::formatRaw( SiteStats::edits(), $raw );
+               return self::formatRaw( SiteStats::edits(), $raw, $parser->getFunctionLang() );
        }
+
        public static function pagesinnamespace( $parser, $namespace = 0, $raw = null ) {
-               return self::formatRaw( SiteStats::pagesInNs( intval( $namespace ) ), $raw );
+               return self::formatRaw(
+                       SiteStats::pagesInNs( intval( $namespace ) ),
+                       $raw,
+                       $parser->getFunctionLang()
+               );
        }
        public static function numberingroup( $parser, $name = '', $raw = null ) {
-               return self::formatRaw( SiteStats::numberingroup( strtolower( $name ) ), $raw );
+               return self::formatRaw(
+                       SiteStats::numberingroup( strtolower( $name ) ),
+                       $raw,
+                       $parser->getFunctionLang()
+               );
        }
 
        /**
@@ -729,7 +755,7 @@ class CoreParserFunctions {
 
                $title = Title::makeTitleSafe( NS_CATEGORY, $name );
                if ( !$title ) { # invalid title
-                       return self::formatRaw( 0, $raw );
+                       return self::formatRaw( 0, $raw, $parser->getFunctionLang() );
                }
                $wgContLang->findVariantLink( $name, $title, true );
 
@@ -755,7 +781,7 @@ class CoreParserFunctions {
                }
 
                $count = $cache[$name][$type];
-               return self::formatRaw( $count, $raw );
+               return self::formatRaw( $count, $raw, $parser->getFunctionLang() );
        }
 
        /**
@@ -771,7 +797,7 @@ class CoreParserFunctions {
                $title = Title::newFromText( $page );
 
                if ( !is_object( $title ) ) {
-                       return self::formatRaw( 0, $raw );
+                       return self::formatRaw( 0, $raw, $parser->getFunctionLang() );
                }
 
                // fetch revision from cache/database and return the value
@@ -781,7 +807,7 @@ class CoreParserFunctions {
                        // We've had bugs where rev_len was not being recorded for empty pages, see T135414
                        $length = 0;
                }
-               return self::formatRaw( $length, $raw );
+               return self::formatRaw( $length, $raw, $parser->getFunctionLang() );
        }
 
        /**
index 13dae8f..1ca9dac 100644 (file)
@@ -88,7 +88,7 @@ class Parser {
        # Constants needed for external link processing
        # Everything except bracket, space, or control characters
        # \p{Zs} is unicode 'separator, space' category. It covers the space 0x20
-       # as well as U+3000 is IDEOGRAPHIC SPACE for bug 19052
+       # as well as U+3000 is IDEOGRAPHIC SPACE for T21052
        const EXT_LINK_URL_CLASS = '[^][<>"\\x00-\\x20\\x7F\p{Zs}]';
        # Simplified expression to match an IPv4 or IPv6 address, or
        # at least one character of a host name (embeds EXT_LINK_URL_CLASS)
@@ -271,7 +271,7 @@ class Parser {
                        # Preprocessor_Hash is much faster than Preprocessor_DOM under HipHop
                        $this->mPreprocessorClass = 'Preprocessor_Hash';
                } elseif ( extension_loaded( 'domxml' ) ) {
-                       # PECL extension that conflicts with the core DOM extension (bug 13770)
+                       # PECL extension that conflicts with the core DOM extension (T15770)
                        wfDebug( "Warning: you have the obsolete domxml extension for PHP. Please remove it!\n" );
                        $this->mPreprocessorClass = 'Preprocessor_Hash';
                } elseif ( extension_loaded( 'dom' ) ) {
@@ -300,7 +300,7 @@ class Parser {
        public function __clone() {
                $this->mInParse = false;
 
-               // Bug 56226: When you create a reference "to" an object field, that
+               // T58226: When you create a reference "to" an object field, that
                // makes the object field itself be a reference too (until the other
                // reference goes out of scope). When cloning, any field that's a
                // reference is copied as a reference in the new object. Both of these
@@ -357,7 +357,7 @@ class Parser {
 
                $this->mStripState = new StripState;
 
-               # Clear these on every parse, bug 4549
+               # Clear these on every parse, T6549
                $this->mTplRedirCache = $this->mTplDomCache = [];
 
                $this->mShowToc = true;
@@ -672,7 +672,7 @@ class Parser {
        }
 
        /**
-        * Process the wikitext for the "?preload=" feature. (bug 5210)
+        * Process the wikitext for the "?preload=" feature. (T7210)
         *
         * "<noinclude>", "<includeonly>" etc. are parsed as for template
         * transclusion, comments, templates, arguments, tags hooks and parser
@@ -1181,9 +1181,10 @@ class Parser {
                                        # A cell could contain both parameters and data
                                        $cell_data = explode( '|', $cell, 2 );
 
-                                       # Bug 553: Note that a '|' inside an invalid link should not
+                                       # T2553: Note that a '|' inside an invalid link should not
                                        # be mistaken as delimiting cell parameters
-                                       if ( strpos( $cell_data[0], '[[' ) !== false ) {
+                                       # Bug T153140: Neither should language converter markup.
+                                       if ( preg_match( '/\[\[|-\{/', $cell_data[0] ) === 1 ) {
                                                $cell = "{$previous}<{$last_tag}>{$cell}";
                                        } elseif ( count( $cell_data ) == 1 ) {
                                                $cell = "{$previous}<{$last_tag}>{$cell_data[0]}";
@@ -1319,12 +1320,12 @@ class Parser {
 
                # Clean up special characters, only run once, next-to-last before doBlockLevels
                $fixtags = [
-                       # french spaces, last one Guillemet-left
+                       # French spaces, last one Guillemet-left
                        # only if there is something before the space
                        '/(.) (?=\\?|:|;|!|%|\\302\\273)/' => '\\1&#160;',
                        # french spaces, Guillemet-right
                        '/(\\302\\253) /' => '\\1&#160;',
-                       '/&#160;(!\s*important)/' => ' \\1', # Beware of CSS magic word !important, bug #11874.
+                       '/&#160;(!\s*important)/' => ' \\1', # Beware of CSS magic word !important, T13874.
                ];
                $text = preg_replace( array_keys( $fixtags ), array_values( $fixtags ), $text );
 
@@ -1367,14 +1368,14 @@ class Parser {
                        }
                } else {
                        # attempt to sanitize at least some nesting problems
-                       # (bug #2702 and quite a few others)
+                       # (T4702 and quite a few others)
                        $tidyregs = [
                                # ''Something [http://www.cool.com cool''] -->
                                # <i>Something</i><a href="http://www.cool.com"..><i>cool></i></a>
                                '/(<([bi])>)(<([bi])>)?([^<]*)(<\/?a[^<]*>)([^<]*)(<\/\\4>)?(<\/\\2>)/' =>
                                '\\1\\3\\5\\8\\9\\6\\1\\3\\7\\8\\9',
                                # fix up an anchor inside another anchor, only
-                               # at least for a single single nested link (bug 3695)
+                               # at least for a single single nested link (T5695)
                                '/(<a[^>]+>)([^<]*)(<a[^>]+>[^<]*)<\/a>(.*)<\/a>/' =>
                                '\\1\\2</a>\\3</a>\\1\\4</a>',
                                # fix div inside inline elements- doBlockLevels won't wrap a line which
@@ -1639,7 +1640,7 @@ class Parser {
                        $thislen = strlen( $arr[$i] );
                        // If there are ever four apostrophes, assume the first is supposed to
                        // be text, and the remaining three constitute mark-up for bold text.
-                       // (bug 13227: ''''foo'''' turns into ' ''' foo ' ''')
+                       // (T15227: ''''foo'''' turns into ' ''' foo ' ''')
                        if ( $thislen == 4 ) {
                                $arr[$i - 1] .= "'";
                                $arr[$i] = "'''";
@@ -1647,7 +1648,7 @@ class Parser {
                        } elseif ( $thislen > 5 ) {
                                // If there are more than 5 apostrophes in a row, assume they're all
                                // text except for the last 5.
-                               // (bug 13227: ''''''foo'''''' turns into ' ''''' foo ' ''''')
+                               // (T15227: ''''''foo'''''' turns into ' ''''' foo ' ''''')
                                $arr[$i - 1] .= str_repeat( "'", $thislen - 5 );
                                $arr[$i] = "'''''";
                                $thislen = 5;
@@ -2169,9 +2170,9 @@ class Parser {
                                # If we get a ] at the beginning of $m[3] that means we have a link that's something like:
                                # [[Image:Foo.jpg|[http://example.com desc]]] <- having three ] in a row fucks up,
                                # the real problem is with the $e1 regex
-                               # See bug 1300.
+                               # See T1500.
                                # Still some problems for cases where the ] is meant to be outside punctuation,
-                               # and no image is in sight. See bug 2095.
+                               # and no image is in sight. See T4095.
                                if ( $text !== ''
                                        && substr( $m[3], 0, 1 ) === ']'
                                        && strpos( $text, '[' ) !== false
@@ -2276,7 +2277,7 @@ class Parser {
                        if ( $wasblank ) {
                                $text = $link;
                        } else {
-                               # Bug 4598 madness. Handle the quotes only if they come from the alternate part
+                               # T6598 madness. Handle the quotes only if they come from the alternate part
                                # [[Lista d''e paise d''o munno]] -> <a href="...">Lista d''e paise d''o munno</a>
                                # [[Criticism of Harry Potter|Criticism of ''Harry Potter'']]
                                #    -> <a href="Criticism of Harry Potter">Criticism of <i>Harry Potter</i></a>
@@ -2292,7 +2293,7 @@ class Parser {
                                                in_array( $iw, $wgExtraInterlanguageLinkPrefixes )
                                        )
                                ) {
-                                       # Bug 24502: filter duplicates
+                                       # T26502: filter duplicates
                                        if ( !isset( $this->mLangLinkLanguages[$iw] ) ) {
                                                $this->mLangLinkLanguages[$iw] = true;
                                                $this->mOutput->addLanguageLink( $nt->getFullText() );
@@ -2324,7 +2325,7 @@ class Parser {
                                                continue;
                                        }
                                } elseif ( $ns == NS_CATEGORY ) {
-                                       $s = rtrim( $s . "\n" ); # bug 87
+                                       $s = rtrim( $s . "\n" ); # T2087
 
                                        if ( $wasblank ) {
                                                $sortkey = $this->getDefaultSort();
@@ -2337,7 +2338,7 @@ class Parser {
                                        $this->mOutput->addCategory( $nt->getDBkey(), $sortkey );
 
                                        /**
-                                        * Strip the whitespace Category links produce, see bug 87
+                                        * Strip the whitespace Category links produce, see T2087
                                         */
                                        $s .= trim( $prefix . $trail, "\n" ) == '' ? '' : $prefix . $trail;
 
@@ -2606,7 +2607,7 @@ class Parser {
                                $subjPage = $this->mTitle->getSubjectPage();
                                $value = wfEscapeWikiText( $subjPage->getPrefixedURL() );
                                break;
-                       case 'pageid': // requested in bug 23427
+                       case 'pageid': // requested in T25427
                                $pageid = $this->getTitle()->getArticleID();
                                if ( $pageid == 0 ) {
                                        # 0 means the page doesn't exist in the database,
@@ -2717,7 +2718,7 @@ class Parser {
                                $value = $pageLang->formatNum( MWTimestamp::getInstance( $ts )->format( 'H' ), true );
                                break;
                        case 'currentweek':
-                               # @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to
+                               # @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to
                                # int to remove the padding
                                $value = $pageLang->formatNum( (int)MWTimestamp::getInstance( $ts )->format( 'W' ) );
                                break;
@@ -2743,7 +2744,7 @@ class Parser {
                                $value = $pageLang->formatNum( MWTimestamp::getLocalInstance( $ts )->format( 'H' ), true );
                                break;
                        case 'localweek':
-                               # @bug 4594 PHP5 has it zero padded, PHP4 does not, cast to
+                               # @bug T6594 PHP5 has it zero padded, PHP4 does not, cast to
                                # int to remove the padding
                                $value = $pageLang->formatNum( (int)MWTimestamp::getLocalInstance( $ts )->format( 'W' ) );
                                break;
@@ -2840,7 +2841,7 @@ class Parser {
         *     included. Default is to assume a direct page view.
         *
         * The generated DOM tree must depend only on the input text and the flags.
-        * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of bug 4899.
+        * The DOM tree must be the same in OT_HTML and OT_WIKI mode, to avoid a regression of T6899.
         *
         * Any flag added to the $flags parameter here, or any other parameter liable to cause a
         * change in the DOM tree for a given text, must be passed through the section identifier
@@ -3275,7 +3276,7 @@ class Parser {
                        && !$piece['lineStart']
                        && preg_match( '/^(?:{\\||:|;|#|\*)/', $text )
                ) {
-                       # Bug 529: if the template begins with a table or block-level
+                       # T2529: if the template begins with a table or block-level
                        # element, it should be treated as beginning a new line.
                        # This behavior is somewhat controversial.
                        $text = "\n" . $text;
@@ -3284,7 +3285,7 @@ class Parser {
                if ( is_string( $text ) && !$this->incrementIncludeSize( 'post-expand', strlen( $text ) ) ) {
                        # Error, oversize inclusion
                        if ( $titleText !== false ) {
-                               # Make a working, properly escaped link if possible (bug 23588)
+                               # Make a working, properly escaped link if possible (T25588)
                                $text = "[[:$titleText]]";
                        } else {
                                # This will probably not be a working link, but at least it may
@@ -3968,9 +3969,8 @@ class Parser {
                ) {
                        $this->addTrackingCategory( 'hidden-category-category' );
                }
-               # (bug 8068) Allow control over whether robots index a page.
-               # @todo FIXME: Bug 14899: __INDEX__ always overrides __NOINDEX__ here!  This
-               # is not desirable, the last one on the page should win.
+               # (T10068) Allow control over whether robots index a page.
+               # __INDEX__ always overrides __NOINDEX__, see T16899
                if ( isset( $this->mDoubleUnderscores['noindex'] ) && $this->mTitle->canUseNoindex() ) {
                        $this->mOutput->setIndexPolicy( 'noindex' );
                        $this->addTrackingCategory( 'noindex-category' );
@@ -4177,11 +4177,11 @@ class Parser {
 
                        # Strip out HTML (first regex removes any tag not allowed)
                        # Allowed tags are:
-                       # * <sup> and <sub> (bug 8393)
-                       # * <i> (bug 26375)
+                       # * <sup> and <sub> (T10393)
+                       # * <i> (T28375)
                        # * <b> (r105284)
-                       # * <bdi> (bug 72884)
-                       # * <span dir="rtl"> and <span dir="ltr"> (bug 35167)
+                       # * <bdi> (T74884)
+                       # * <span dir="rtl"> and <span dir="ltr"> (T37167)
                        # * <s> and <strike> (T35715)
                        # We strip any parameter from accepted tags (second regex), except dir="rtl|ltr" from <span>,
                        # to allow setting directionality in toc items.
@@ -4232,7 +4232,7 @@ class Parser {
                                        'noninitial' );
                        }
 
-                       # HTML names must be case-insensitively unique (bug 10721).
+                       # HTML names must be case-insensitively unique (T12721).
                        # This does not apply to Unicode characters per
                        # https://www.w3.org/TR/html5/infrastructure.html#case-sensitivity-and-string-comparison
                        # @todo FIXME: We may be changing them depending on the current locale.
@@ -4463,7 +4463,7 @@ class Parser {
                # the database, we use $wgContLang here in order to give
                # everyone the same signature and use the default one rather
                # than the one selected in each user's preferences.
-               # (see also bug 12815)
+               # (see also T14815)
                $ts = $this->mOptions->getTimestamp();
                $timestamp = MWTimestamp::getLocalInstance( $ts );
                $ts = $timestamp->format( 'YmdHis' );
@@ -5019,7 +5019,10 @@ class Parser {
                                // FIXME: Doing recursiveTagParse at this stage, and the trim before
                                // splitting on '|' is a bit odd, and different from makeImage.
                                $matches[3] = $this->recursiveTagParse( trim( $matches[3] ) );
-                               $parameterMatches = StringUtils::explode( '|', $matches[3] );
+                               // Protect LanguageConverter markup
+                               $parameterMatches = StringUtils::delimiterExplode(
+                                       '-{', '}-', '|', $matches[3], true /* nested */
+                               );
 
                                foreach ( $parameterMatches as $parameterMatch ) {
                                        list( $magicName, $match ) = $mwArray->matchVariableStartToEnd( $parameterMatch );
@@ -5036,6 +5039,11 @@ class Parser {
                                                        $addr = self::EXT_LINK_ADDR;
                                                        $prots = $this->mUrlProtocols;
                                                        // check to see if link matches an absolute url, if not then it must be a wiki link.
+                                                       if ( preg_match( '/^-{R|(.*)}-$/', $linkValue ) ) {
+                                                               // Result of LanguageConverter::markNoConversion
+                                                               // invoked on an external link.
+                                                               $linkValue = substr( $linkValue, 4, -2 );
+                                                       }
                                                        if ( preg_match( "/^($prots)$addr$chars*$/u", $linkValue ) ) {
                                                                $link = $linkValue;
                                                        } else {
@@ -5151,7 +5159,10 @@ class Parser {
                #  * bottom
                #  * text-bottom
 
-               $parts = StringUtils::explode( "|", $options );
+               # Protect LanguageConverter markup when splitting into parts
+               $parts = StringUtils::delimiterExplode(
+                       '-{', '}-', '|', $options, true /* allow nesting */
+               );
 
                # Give extensions a chance to select the file revision for us
                $options = [];
@@ -5199,7 +5210,7 @@ class Parser {
                                                        $validated = true;
                                                }
                                        }
-                                       # else no validation -- bug 13436
+                                       # else no validation -- T15436
                                } else {
                                        if ( $type === 'handler' ) {
                                                # Validate handler parameter
@@ -5438,14 +5449,14 @@ class Parser {
         * External callers should use the getSection and replaceSection methods.
         *
         * @param string $text Page wikitext
-        * @param string|number $sectionId A section identifier string of the form:
+        * @param string|int $sectionId A section identifier string of the form:
         *   "<flag1> - <flag2> - ... - <section number>"
         *
         * Currently the only recognised flag is "T", which means the target section number
         * was derived during a template inclusion parse, in other words this is a template
         * section edit link. If no flags are given, it was an ordinary section edit link.
         * This flag is required to avoid a section numbering mismatch when a section is
-        * enclosed by "<includeonly>" (bug 6563).
+        * enclosed by "<includeonly>" (T8563).
         *
         * The section number 0 pulls the text before the first heading; other numbers will
         * pull the given section along with its lower-level subsections. If the section is
@@ -5579,7 +5590,7 @@ class Parser {
         * If a section contains subsections, these are also returned.
         *
         * @param string $text Text to look in
-        * @param string|number $sectionId Section identifier as a number or string
+        * @param string|int $sectionId Section identifier as a number or string
         * (e.g. 0, 1 or 'T-1').
         * @param string $defaultText Default to return if section is not found
         *
@@ -5595,7 +5606,7 @@ class Parser {
         * section does not exist, $oldtext is returned unchanged.
         *
         * @param string $oldText Former text of the article
-        * @param string|number $sectionId Section identifier as a number or string
+        * @param string|int $sectionId Section identifier as a number or string
         * (e.g. 0, 1 or 'T-1').
         * @param string $newText Replacing text
         *
@@ -5986,7 +5997,7 @@ class Parser {
                        return $parsedWidthParam;
                }
                $m = [];
-               # (bug 13500) In both cases (width/height and width only),
+               # (T15500) In both cases (width/height and width only),
                # permit trailing "px" for backward compatibility.
                if ( preg_match( '/^([0-9]*)x([0-9]*)\s*(?:px)?\s*$/', $value, $m ) ) {
                        $width = intval( $m[1] );
index b0768b6..bfaa4f7 100644 (file)
@@ -215,7 +215,7 @@ class ParserOutput extends CacheTime {
        private $mMaxAdaptiveExpiry = INF;
 
        const EDITSECTION_REGEX =
-               '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#';
+               '#<(?:mw:)?editsection page="(.*?)" section="(.*?)"(?:/>|>(.*?)(</(?:mw:)?editsection>))#s';
 
        // finalizeAdaptiveCacheExpiry() uses TTL = MAX( m * PARSE_TIME + b, MIN_AR_TTL)
        // Current values imply that m=3933.333333 and b=-333.333333
index cc98abd..426b550 100644 (file)
@@ -48,7 +48,13 @@ abstract class Preprocessor {
                        'names' => [ 2 => null ],
                        'min' => 2,
                        'max' => 2,
-               ]
+               ],
+               '-{' => [
+                       'end' => '}-',
+                       'names' => [ 1 => null ],
+                       'min' => 1,
+                       'max' => 1,
+               ],
        ];
 
        /**
index 5da7cd7..950d66d 100644 (file)
@@ -193,6 +193,8 @@ class Preprocessor_DOM extends Preprocessor {
         * @return string
         */
        public function preprocessToXml( $text, $flags = 0 ) {
+               global $wgDisableLangConversion;
+
                $forInclusion = $flags & Parser::PTD_FOR_INCLUSION;
 
                $xmlishElements = $this->parser->getStripList();
@@ -220,6 +222,10 @@ class Preprocessor_DOM extends Preprocessor {
                $stack = new PPDStack;
 
                $searchBase = "[{<\n"; # }
+               if ( !$wgDisableLangConversion ) {
+                       $searchBase .= '-';
+               }
+
                // For fast reverse searches
                $revText = strrev( $text );
                $lengthText = strlen( $text );
@@ -298,7 +304,10 @@ class Preprocessor_DOM extends Preprocessor {
                                                break;
                                        }
                                } else {
-                                       $curChar = $text[$i];
+                                       $curChar = $curTwoChar = $text[$i];
+                                       if ( ( $i + 1 ) < $lengthText ) {
+                                               $curTwoChar .= $text[$i + 1];
+                                       }
                                        if ( $curChar == '|' ) {
                                                $found = 'pipe';
                                        } elseif ( $curChar == '=' ) {
@@ -311,11 +320,20 @@ class Preprocessor_DOM extends Preprocessor {
                                                } else {
                                                        $found = 'line-start';
                                                }
+                                       } elseif ( $curTwoChar == $currentClosing ) {
+                                               $found = 'close';
+                                               $curChar = $curTwoChar;
                                        } elseif ( $curChar == $currentClosing ) {
                                                $found = 'close';
+                                       } elseif ( isset( $this->rules[$curTwoChar] ) ) {
+                                               $curChar = $curTwoChar;
+                                               $found = 'open';
+                                               $rule = $this->rules[$curChar];
                                        } elseif ( isset( $this->rules[$curChar] ) ) {
                                                $found = 'open';
                                                $rule = $this->rules[$curChar];
+                                       } elseif ( $curChar == '-' ) {
+                                               $found = 'dash';
                                        } else {
                                                # Some versions of PHP have a strcspn which stops on null characters
                                                # Ignore and continue
@@ -595,7 +613,8 @@ class Preprocessor_DOM extends Preprocessor {
                                // input pointer.
                        } elseif ( $found == 'open' ) {
                                # count opening brace characters
-                               $count = strspn( $text, $curChar, $i );
+                               $curLen = strlen( $curChar );
+                               $count = ( $curLen > 1 ) ? 1 : strspn( $text, $curChar, $i );
 
                                # we need to add to stack only if opening brace count is enough for one of the rules
                                if ( $count >= $rule['min'] ) {
@@ -615,12 +634,13 @@ class Preprocessor_DOM extends Preprocessor {
                                        # Add literal brace(s)
                                        $accum .= htmlspecialchars( str_repeat( $curChar, $count ) );
                                }
-                               $i += $count;
+                               $i += $curLen * $count;
                        } elseif ( $found == 'close' ) {
                                $piece = $stack->top;
                                # lets check if there are enough characters for closing brace
                                $maxCount = $piece->count;
-                               $count = strspn( $text, $curChar, $i, $maxCount );
+                               $curLen = strlen( $curChar );
+                               $count = ( $curLen > 1 ) ? 1 : strspn( $text, $curChar, $i, $maxCount );
 
                                # check for maximum matching characters (if there are 5 closing
                                # characters, we will probably need only 3 - depending on the rules)
@@ -643,7 +663,7 @@ class Preprocessor_DOM extends Preprocessor {
                                        # No matching element found in callback array
                                        # Output a literal closing brace and continue
                                        $accum .= htmlspecialchars( str_repeat( $curChar, $count ) );
-                                       $i += $count;
+                                       $i += $curLen * $count;
                                        continue;
                                }
                                $name = $rule['names'][$matchingCount];
@@ -682,7 +702,7 @@ class Preprocessor_DOM extends Preprocessor {
                                }
 
                                # Advance input pointer
-                               $i += $matchingCount;
+                               $i += $curLen * $matchingCount;
 
                                # Unwind the stack
                                $stack->pop();
@@ -716,6 +736,9 @@ class Preprocessor_DOM extends Preprocessor {
                                $stack->getCurrentPart()->eqpos = strlen( $accum );
                                $accum .= '=';
                                ++$i;
+                       } elseif ( $found == 'dash' ) {
+                               $accum .= '-';
+                               ++$i;
                        }
                }
 
index 8a4637e..1317e60 100644 (file)
@@ -117,6 +117,8 @@ class Preprocessor_Hash extends Preprocessor {
         * @return PPNode_Hash_Tree
         */
        public function preprocessToObj( $text, $flags = 0 ) {
+               global $wgDisableLangConversion;
+
                $tree = $this->cacheGetTree( $text, $flags );
                if ( $tree !== false ) {
                        $store = json_decode( $tree );
@@ -152,6 +154,10 @@ class Preprocessor_Hash extends Preprocessor {
                $stack = new PPDStack_Hash;
 
                $searchBase = "[{<\n";
+               if ( !$wgDisableLangConversion ) {
+                       $searchBase .= '-';
+               }
+
                // For fast reverse searches
                $revText = strrev( $text );
                $lengthText = strlen( $text );
@@ -229,7 +235,10 @@ class Preprocessor_Hash extends Preprocessor {
                                                break;
                                        }
                                } else {
-                                       $curChar = $text[$i];
+                                       $curChar = $curTwoChar = $text[$i];
+                                       if ( ( $i + 1 ) < $lengthText ) {
+                                               $curTwoChar .= $text[$i + 1];
+                                       }
                                        if ( $curChar == '|' ) {
                                                $found = 'pipe';
                                        } elseif ( $curChar == '=' ) {
@@ -242,11 +251,20 @@ class Preprocessor_Hash extends Preprocessor {
                                                } else {
                                                        $found = 'line-start';
                                                }
+                                       } elseif ( $curTwoChar == $currentClosing ) {
+                                               $found = 'close';
+                                               $curChar = $curTwoChar;
                                        } elseif ( $curChar == $currentClosing ) {
                                                $found = 'close';
+                                       } elseif ( isset( $this->rules[$curTwoChar] ) ) {
+                                               $curChar = $curTwoChar;
+                                               $found = 'open';
+                                               $rule = $this->rules[$curChar];
                                        } elseif ( isset( $this->rules[$curChar] ) ) {
                                                $found = 'open';
                                                $rule = $this->rules[$curChar];
+                                       } elseif ( $curChar == '-' ) {
+                                               $found = 'dash';
                                        } else {
                                                # Some versions of PHP have a strcspn which stops on null characters
                                                # Ignore and continue
@@ -538,7 +556,8 @@ class Preprocessor_Hash extends Preprocessor {
                                // input pointer.
                        } elseif ( $found == 'open' ) {
                                # count opening brace characters
-                               $count = strspn( $text, $curChar, $i );
+                               $curLen = strlen( $curChar );
+                               $count = ( $curLen > 1 ) ? 1 : strspn( $text, $curChar, $i );
 
                                # we need to add to stack only if opening brace count is enough for one of the rules
                                if ( $count >= $rule['min'] ) {
@@ -557,12 +576,13 @@ class Preprocessor_Hash extends Preprocessor {
                                        # Add literal brace(s)
                                        self::addLiteral( $accum, str_repeat( $curChar, $count ) );
                                }
-                               $i += $count;
+                               $i += $curLen * $count;
                        } elseif ( $found == 'close' ) {
                                $piece = $stack->top;
                                # lets check if there are enough characters for closing brace
                                $maxCount = $piece->count;
-                               $count = strspn( $text, $curChar, $i, $maxCount );
+                               $curLen = strlen( $curChar );
+                               $count = ( $curLen > 1 ) ? 1 : strspn( $text, $curChar, $i, $maxCount );
 
                                # check for maximum matching characters (if there are 5 closing
                                # characters, we will probably need only 3 - depending on the rules)
@@ -585,7 +605,7 @@ class Preprocessor_Hash extends Preprocessor {
                                        # No matching element found in callback array
                                        # Output a literal closing brace and continue
                                        self::addLiteral( $accum, str_repeat( $curChar, $count ) );
-                                       $i += $count;
+                                       $i += $curLen * $count;
                                        continue;
                                }
                                $name = $rule['names'][$matchingCount];
@@ -627,7 +647,7 @@ class Preprocessor_Hash extends Preprocessor {
                                }
 
                                # Advance input pointer
-                               $i += $matchingCount;
+                               $i += $curLen * $matchingCount;
 
                                # Unwind the stack
                                $stack->pop();
@@ -661,6 +681,9 @@ class Preprocessor_Hash extends Preprocessor {
                                $accum[] = [ 'equals', [ '=' ] ];
                                $stack->getCurrentPart()->eqpos = count( $accum ) - 1;
                                ++$i;
+                       } elseif ( $found == 'dash' ) {
+                               self::addLiteral( $accum, '-' );
+                               ++$i;
                        }
                }
 
index c929797..78d624c 100644 (file)
@@ -79,7 +79,7 @@ abstract class ParameterizedPassword extends Password {
        }
 
        public function needsUpdate() {
-               return parent::needsUpdate() || $this->params !== $this->getDefaultParams();
+               return $this->params !== $this->getDefaultParams();
        }
 
        public function toString() {
index 13d1e6d..c8a0267 100644 (file)
@@ -138,8 +138,7 @@ abstract class Password {
         *
         * @return bool True if needs update, false otherwise
         */
-       public function needsUpdate() {
-       }
+       abstract public function needsUpdate();
 
        /**
         * Compare one Password object to this object
diff --git a/includes/registration/CoreVersionChecker.php b/includes/registration/CoreVersionChecker.php
deleted file mode 100644 (file)
index f64d826..0000000
+++ /dev/null
@@ -1,68 +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
- */
-
-use Composer\Semver\VersionParser;
-use Composer\Semver\Constraint\Constraint;
-
-/**
- * @since 1.26
- */
-class CoreVersionChecker {
-
-       /**
-        * @var Constraint|bool representing $wgVersion
-        */
-       private $coreVersion = false;
-
-       /**
-        * @var VersionParser
-        */
-       private $versionParser;
-
-       /**
-        * @param string $coreVersion Current version of core
-        */
-       public function __construct( $coreVersion ) {
-               $this->versionParser = new VersionParser();
-               try {
-                       $this->coreVersion = new Constraint(
-                               '==',
-                               $this->versionParser->normalize( $coreVersion )
-                       );
-               } catch ( UnexpectedValueException $e ) {
-                       // Non-parsable version, don't fatal.
-               }
-       }
-
-       /**
-        * Check that the provided constraint is compatible with the current version of core
-        *
-        * @param string $constraint Something like ">= 1.26"
-        * @return bool
-        */
-       public function check( $constraint ) {
-               if ( $this->coreVersion === false ) {
-                       // Couldn't parse the core version, so we can't check anything
-                       return true;
-               }
-
-               return $this->versionParser->parseConstraints( $constraint )
-                       ->matches( $this->coreVersion );
-       }
-}
index f6e76af..8142111 100644 (file)
@@ -75,11 +75,7 @@ class ExtensionJsonValidator {
                }
 
                $version = $data->manifest_version;
-               if ( $version !== ExtensionRegistry::MANIFEST_VERSION ) {
-                       $schemaPath = __DIR__ . "/../../docs/extension.schema.v$version.json";
-               } else {
-                       $schemaPath = __DIR__ . '/../../docs/extension.schema.json';
-               }
+               $schemaPath = __DIR__ . "/../../docs/extension.schema.v$version.json";
 
                // Not too old
                if ( $version < ExtensionRegistry::OLDEST_MANIFEST_VERSION ) {
index d967132..1212f99 100644 (file)
@@ -216,13 +216,7 @@ class ExtensionProcessor implements Processor {
        }
 
        public function getRequirements( array $info ) {
-               $requirements = [];
-               $key = ExtensionRegistry::MEDIAWIKI_CORE;
-               if ( isset( $info['requires'][$key] ) ) {
-                       $requirements[$key] = $info['requires'][$key];
-               }
-
-               return $requirements;
+               return isset( $info['requires'] ) ? $info['requires'] : [];
        }
 
        protected function extractHooks( array $info ) {
index 70dc624..c5b2150 100644 (file)
@@ -31,7 +31,7 @@ class ExtensionRegistry {
        /**
         * Bump whenever the registration cache needs resetting
         */
-       const CACHE_VERSION = 4;
+       const CACHE_VERSION = 5;
 
        /**
         * Special key that defines the merge strategy
@@ -203,8 +203,9 @@ class ExtensionRegistry {
                $autoloadClasses = [];
                $autoloaderPaths = [];
                $processor = new ExtensionProcessor();
+               $versionChecker = new VersionChecker( $wgVersion );
+               $extDependencies = [];
                $incompatible = [];
-               $coreVersionParser = new CoreVersionChecker( $wgVersion );
                foreach ( $queue as $path => $mtime ) {
                        $json = file_get_contents( $path );
                        if ( $json === false ) {
@@ -215,25 +216,13 @@ class ExtensionRegistry {
                                throw new Exception( "$path is not a valid JSON file." );
                        }
 
-                       // Check any constraints against MediaWiki core
-                       $requires = $processor->getRequirements( $info );
-                       if ( isset( $requires[self::MEDIAWIKI_CORE] )
-                               && !$coreVersionParser->check( $requires[self::MEDIAWIKI_CORE] )
-                       ) {
-                               // Doesn't match, mark it as incompatible.
-                               $incompatible[] = "{$info['name']} is not compatible with the current "
-                                       . "MediaWiki core (version {$wgVersion}), it requires: " . $requires[self::MEDIAWIKI_CORE]
-                                       . '.';
-                               continue;
-                       }
-
                        if ( !isset( $info['manifest_version'] ) ) {
                                // For backwards-compatability, assume a version of 1
                                $info['manifest_version'] = 1;
                        }
                        $version = $info['manifest_version'];
                        if ( $version < self::OLDEST_MANIFEST_VERSION || $version > self::MANIFEST_VERSION ) {
-                               throw new Exception( "$path: unsupported manifest_version: {$version}" );
+                               $incompatible[] = "$path: unsupported manifest_version: {$version}";
                        }
 
                        $autoload = $this->processAutoLoader( dirname( $path ), $info );
@@ -241,12 +230,30 @@ class ExtensionRegistry {
                        $GLOBALS['wgAutoloadClasses'] += $autoload;
                        $autoloadClasses += $autoload;
 
+                       // get all requirements/dependencies for this extension
+                       $requires = $processor->getRequirements( $info );
+
+                       // validate the information needed and add the requirements
+                       if ( is_array( $requires ) && $requires && isset( $info['name'] ) ) {
+                               $extDependencies[$info['name']] = $requires;
+                       }
+
                        // Get extra paths for later inclusion
                        $autoloaderPaths = array_merge( $autoloaderPaths,
                                $processor->getExtraAutoloaderPaths( dirname( $path ), $info ) );
                        // Compatible, read and extract info
                        $processor->extractInfo( $path, $info, $version );
                }
+               $data = $processor->getExtractedInfo();
+
+               // check for incompatible extensions
+               $incompatible = array_merge(
+                       $incompatible,
+                       $versionChecker
+                               ->setLoadedExtensionsAndSkins( $data['credits'] )
+                               ->checkArray( $extDependencies )
+               );
+
                if ( $incompatible ) {
                        if ( count( $incompatible ) === 1 ) {
                                throw new Exception( $incompatible[0] );
@@ -254,7 +261,7 @@ class ExtensionRegistry {
                                throw new Exception( implode( "\n", $incompatible ) );
                        }
                }
-               $data = $processor->getExtractedInfo();
+
                // Need to set this so we can += to it later
                $data['globals']['wgAutoloadClasses'] = [];
                $data['autoload'] = $autoloadClasses;
diff --git a/includes/registration/VersionChecker.php b/includes/registration/VersionChecker.php
new file mode 100644 (file)
index 0000000..5aaaa1b
--- /dev/null
@@ -0,0 +1,211 @@
+<?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
+ *
+ * @author Legoktm
+ * @author Florian Schmidt
+ */
+
+use Composer\Semver\VersionParser;
+use Composer\Semver\Constraint\Constraint;
+
+/**
+ * Provides functions to check a set of extensions with dependencies against
+ * a set of loaded extensions and given version information.
+ *
+ * @since 1.29
+ */
+class VersionChecker {
+       /**
+        * @var Constraint|bool representing $wgVersion
+        */
+       private $coreVersion = false;
+
+       /**
+        * @var array Loaded extensions
+        */
+       private $loaded = [];
+
+       /**
+        * @var VersionParser
+        */
+       private $versionParser;
+
+       /**
+        * @param string $coreVersion Current version of core
+        */
+       public function __construct( $coreVersion ) {
+               $this->versionParser = new VersionParser();
+               $this->setCoreVersion( $coreVersion );
+       }
+
+       /**
+        * Set an array with credits of all loaded extensions and skins.
+        *
+        * @param array $credits An array of installed extensions with credits of them
+        * @return VersionChecker $this
+        */
+       public function setLoadedExtensionsAndSkins( array $credits ) {
+               $this->loaded = $credits;
+
+               return $this;
+       }
+
+       /**
+        * Set MediaWiki core version.
+        *
+        * @param string $coreVersion Current version of core
+        */
+       private function setCoreVersion( $coreVersion ) {
+               try {
+                       $this->coreVersion = new Constraint(
+                               '==',
+                               $this->versionParser->normalize( $coreVersion )
+                       );
+                       $this->coreVersion->setPrettyString( $coreVersion );
+               } catch ( UnexpectedValueException $e ) {
+                       // Non-parsable version, don't fatal.
+               }
+       }
+
+       /**
+        * Check all given dependencies if they are compatible with the named
+        * installed extensions in the $credits array.
+        *
+        * Example $extDependencies:
+        *      {
+        *              'FooBar' => {
+        *                      'MediaWiki' => '>= 1.25.0',
+        *                      'extensions' => {
+        *                              'FooBaz' => '>= 1.25.0'
+        *                      },
+        *                      'skins' => {
+        *                              'BazBar' => '>= 1.0.0'
+        *                      }
+        *              }
+        *      }
+        *
+        * @param array $extDependencies All extensions that depend on other ones
+        * @return array
+        */
+       public function checkArray( array $extDependencies ) {
+               $errors = [];
+               foreach ( $extDependencies as $extension => $dependencies ) {
+                       foreach ( $dependencies as $dependencyType => $values ) {
+                               switch ( $dependencyType ) {
+                                       case ExtensionRegistry::MEDIAWIKI_CORE:
+                                               $mwError = $this->handleMediaWikiDependency( $values, $extension );
+                                               if ( $mwError !== false ) {
+                                                       $errors[] = $mwError;
+                                               }
+                                               break;
+                                       case 'extensions':
+                                       case 'skin':
+                                               foreach ( $values as $dependency => $constraint ) {
+                                                       $extError = $this->handleExtensionDependency( $dependency, $constraint, $extension );
+                                                       if ( $extError !== false ) {
+                                                               $errors[] = $extError;
+                                                       }
+                                               }
+                                               break;
+                                       default:
+                                               throw new UnexpectedValueException( 'Dependency type ' . $dependencyType .
+                                                       ' unknown in ' . $extension );
+                               }
+                       }
+               }
+
+               return $errors;
+       }
+
+       /**
+        * Handle a dependency to MediaWiki core. It will check, if a MediaWiki version constraint was
+        * set with self::setCoreVersion before this call (if not, it will return an empty array) and
+        * checks the version constraint given against it.
+        *
+        * @param string $constraint The required version constraint for this dependency
+        * @param string $checkedExt The Extension, which depends on this dependency
+        * @return bool|string false if no error, or a string with the message
+        */
+       private function handleMediaWikiDependency( $constraint, $checkedExt ) {
+               if ( $this->coreVersion === false ) {
+                       // Couldn't parse the core version, so we can't check anything
+                       return false;
+               }
+
+               // if the installed and required version are compatible, return an empty array
+               if ( $this->versionParser->parseConstraints( $constraint )
+                       ->matches( $this->coreVersion ) ) {
+                       return false;
+               }
+               // otherwise mark this as incompatible.
+               return "{$checkedExt} is not compatible with the current "
+                       . "MediaWiki core (version {$this->coreVersion->getPrettyString()}), it requires: "
+                       . "$constraint.";
+       }
+
+       /**
+        * Handle a dependency to another extension.
+        *
+        * @param string $dependencyName The name of the dependency
+        * @param string $constraint The required version constraint for this dependency
+        * @param string $checkedExt The Extension, which depends on this dependency
+        * @return bool|string false for no errors, or a string message
+        */
+       private function handleExtensionDependency( $dependencyName, $constraint, $checkedExt ) {
+               // Check if the dependency is even installed
+               if ( !isset( $this->loaded[$dependencyName] ) ) {
+                       return "{$checkedExt} requires {$dependencyName} to be installed.";
+               }
+               // Check if the dependency has specified a version
+               if ( !isset( $this->loaded[$dependencyName]['version'] ) ) {
+                       // If we depend upon any version, and none is set, that's fine.
+                       if ( $constraint === '*' ) {
+                               wfDebug( "{$dependencyName} does not expose it's version, but {$checkedExt}
+                                       mentions it with constraint '*'. Assume it's ok so." );
+                               return false;
+                       } else {
+                               // Otherwise, mark it as incompatible.
+                               return "{$dependencyName} does not expose it's version, but {$checkedExt}
+                                       requires: {$constraint}.";
+                       }
+               } else {
+                       // Try to get a constraint for the dependency version
+                       try {
+                               $installedVersion = new Constraint(
+                                       '==',
+                                       $this->versionParser->normalize( $this->loaded[$dependencyName]['version'] )
+                               );
+                       } catch ( UnexpectedValueException $e ) {
+                               // Non-parsable version, output an error message that the version
+                               // string is invalid
+                               return "$dependencyName does not have a valid version string.";
+                       }
+                       // Check if the constraint actually matches...
+                       if (
+                               !$this->versionParser->parseConstraints( $constraint )->matches( $installedVersion )
+                       ) {
+                               return "{$checkedExt} is not compatible with the current "
+                                       . "installed version of {$dependencyName} "
+                                       . "({$this->loaded[$dependencyName]['version']}), "
+                                       . "it requires: " . $constraint . '.';
+                       }
+               }
+
+               return false;
+       }
+}
index f9b4b3d..f0b48d5 100644 (file)
@@ -605,6 +605,25 @@ class ResourceLoader implements LoggerAwareInterface {
                return Wikimedia\base_convert( $hash, 16, 36, 7 );
        }
 
+       /**
+        * Add an error to the 'errors' array and log it.
+        *
+        * Should only be called from within respond().
+        *
+        * @since 1.29
+        * @param Exception $e
+        * @param string $msg
+        * @param array $context
+        */
+       protected function outputErrorAndLog( Exception $e, $msg, array $context = [] ) {
+               MWExceptionHandler::logException( $e );
+               $this->logger->warning(
+                       $msg,
+                       $context + [ 'exception' => $e ]
+               );
+               $this->errors[] = self::formatExceptionNoComment( $e );
+       }
+
        /**
         * Helper method to get and combine versions of multiple modules.
         *
@@ -618,7 +637,20 @@ class ResourceLoader implements LoggerAwareInterface {
                        return '';
                }
                $hashes = array_map( function ( $module ) use ( $context ) {
-                       return $this->getModule( $module )->getVersionHash( $context );
+                       try {
+                               return $this->getModule( $module )->getVersionHash( $context );
+                       } catch ( Exception $e ) {
+                               // If modules fail to compute a version, do still consider the versions
+                               // of other modules - don't set an empty string E-Tag for the whole request.
+                               // See also T152266 and StartupModule::getModuleRegistrations().
+                               $this->outputErrorAndLog( $e,
+                                       'Calculating version for "{module}" failed: {exception}',
+                                       [
+                                               'module' => $module,
+                                       ]
+                               );
+                               return '';
+                       }
                }, $moduleNames );
                return self::makeHash( implode( '', $hashes ) );
        }
@@ -693,11 +725,7 @@ class ResourceLoader implements LoggerAwareInterface {
                        // Preload for getCombinedVersion() and for batch makeModuleResponse()
                        $this->preloadModuleInfo( array_keys( $modules ), $context );
                } catch ( Exception $e ) {
-                       MWExceptionHandler::logException( $e );
-                       $this->logger->warning( 'Preloading module info failed: {exception}', [
-                               'exception' => $e
-                       ] );
-                       $this->errors[] = self::formatExceptionNoComment( $e );
+                       $this->outputErrorAndLog( $e, 'Preloading module info failed: {exception}' );
                }
 
                // Combine versions to propagate cache invalidation
@@ -705,11 +733,7 @@ class ResourceLoader implements LoggerAwareInterface {
                try {
                        $versionHash = $this->getCombinedVersion( $context, array_keys( $modules ) );
                } catch ( Exception $e ) {
-                       MWExceptionHandler::logException( $e );
-                       $this->logger->warning( 'Calculating version hash failed: {exception}', [
-                               'exception' => $e
-                       ] );
-                       $this->errors[] = self::formatExceptionNoComment( $e );
+                       $this->outputErrorAndLog( $e, 'Calculating version hash failed: {exception}' );
                }
 
                // See RFC 2616 § 3.11 Entity Tags
@@ -958,7 +982,9 @@ class ResourceLoader implements LoggerAwareInterface {
                        return MWExceptionHandler::getPublicLogMessage( $e );
                }
 
-               return MWExceptionHandler::getLogMessage( $e );
+               return MWExceptionHandler::getLogMessage( $e ) .
+                       "\nBacktrace:\n" .
+                       MWExceptionHandler::getRedactedTraceAsString( $e );
        }
 
        /**
@@ -1059,11 +1085,7 @@ MESSAGE;
                                $out .= $strContent;
 
                        } catch ( Exception $e ) {
-                               MWExceptionHandler::logException( $e );
-                               $this->logger->warning( 'Generating module package failed: {exception}', [
-                                       'exception' => $e
-                               ] );
-                               $this->errors[] = self::formatExceptionNoComment( $e );
+                               $this->outputErrorAndLog( $e, 'Generating module package failed: {exception}' );
 
                                // Respond to client with error-state instead of module implementation
                                $states[$name] = 'error';
index 91e0b02..ef2827c 100644 (file)
@@ -56,7 +56,7 @@ class ResourceLoaderClientHtml {
 
        /**
         * @param ResourceLoaderContext $context
-        * @param aray $target [optional] Custom 'target' parameter for the startup module
+        * @param string|null $target [optional] Custom 'target' parameter for the startup module
         */
        public function __construct( ResourceLoaderContext $context, $target = null ) {
                $this->context = $context;
index 8970620..a99305c 100644 (file)
@@ -194,7 +194,6 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
         * @return string JavaScript code for registering all modules with the client loader
         */
        public function getModuleRegistrations( ResourceLoaderContext $context ) {
-
                $resourceLoader = $context->getResourceLoader();
                $target = $context->getRequest()->getVal( 'target', 'desktop' );
                // Bypass target filter if this request is Special:JavaScriptTest.
@@ -202,6 +201,7 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                $byPassTargetFilter = $this->getConfig()->get( 'EnableJavaScriptTest' ) && $target === 'test';
 
                $out = '';
+               $states = [];
                $registryData = [];
 
                // Get registry data
@@ -219,8 +219,23 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                                continue;
                        }
 
-                       $versionHash = $module->getVersionHash( $context );
-                       if ( strlen( $versionHash ) !== 7 ) {
+                       try {
+                               $versionHash = $module->getVersionHash( $context );
+                       } catch ( Exception $e ) {
+                               // See also T152266 and ResourceLoader::getCombinedVersion()
+                               MWExceptionHandler::logException( $e );
+                               $context->getLogger()->warning(
+                                       'Calculating version for "{module}" failed: {exception}',
+                                       [
+                                               'module' => $name,
+                                               'exception' => $e,
+                                       ]
+                               );
+                               $versionHash = '';
+                               $states[$name] = 'error';
+                       }
+
+                       if ( $versionHash !== '' && strlen( $versionHash ) !== 7 ) {
                                $context->getLogger()->warning(
                                        "Module '{module}' produced an invalid version hash: '{version}'.",
                                        [
@@ -270,6 +285,10 @@ class ResourceLoaderStartUpModule extends ResourceLoaderModule {
                // Register modules
                $out .= "\n" . ResourceLoader::makeLoaderRegisterScript( $registrations );
 
+               if ( $states ) {
+                       $out .= "\n" . ResourceLoader::makeLoaderStateScript( $states );
+               }
+
                return $out;
        }
 
index decabba..32d4891 100644 (file)
@@ -102,10 +102,10 @@ class RevDelArchivedFileItem extends RevDelFileItem {
                        'width' => $file->getWidth(),
                        'height' => $file->getHeight(),
                        'size' => $file->getSize(),
+                       'userhidden' => (bool)$file->isDeleted( Revision::DELETED_USER ),
+                       'commenthidden' => (bool)$file->isDeleted( Revision::DELETED_COMMENT ),
+                       'contenthidden' => (bool)$this->isDeleted(),
                ];
-               $ret += $file->isDeleted( Revision::DELETED_USER ) ? [ 'userhidden' => '' ] : [];
-               $ret += $file->isDeleted( Revision::DELETED_COMMENT ) ? [ 'commenthidden' => '' ] : [];
-               $ret += $this->isDeleted() ? [ 'contenthidden' => '' ] : [];
                if ( $this->canViewContent() ) {
                        $ret += [
                                'url' => SpecialPage::getTitleFor( 'Revisiondelete' )->getLinkURL(
index 06b596e..9beafc9 100644 (file)
@@ -202,10 +202,10 @@ class RevDelFileItem extends RevDelItem {
                        'width' => $file->getWidth(),
                        'height' => $file->getHeight(),
                        'size' => $file->getSize(),
+                       'userhidden' => (bool)$file->isDeleted( Revision::DELETED_USER ),
+                       'commenthidden' => (bool)$file->isDeleted( Revision::DELETED_COMMENT ),
+                       'contenthidden' => (bool)$this->isDeleted(),
                ];
-               $ret += $file->isDeleted( Revision::DELETED_USER ) ? [ 'userhidden' => '' ] : [];
-               $ret += $file->isDeleted( Revision::DELETED_COMMENT ) ? [ 'commenthidden' => '' ] : [];
-               $ret += $this->isDeleted() ? [ 'contenthidden' => '' ] : [];
                if ( !$this->isDeleted() ) {
                        $ret += [
                                'url' => $file->getUrl(),
index 9e76f4c..047d6cf 100644 (file)
@@ -119,16 +119,10 @@ class RevDelLogItem extends RevDelItem {
                        'id' => $logEntry->getId(),
                        'type' => $logEntry->getType(),
                        'action' => $logEntry->getSubtype(),
+                       'userhidden' => (bool)$logEntry->isDeleted( LogPage::DELETED_USER ),
+                       'commenthidden' => (bool)$logEntry->isDeleted( LogPage::DELETED_COMMENT ),
+                       'actionhidden' => (bool)$logEntry->isDeleted( LogPage::DELETED_ACTION ),
                ];
-               $ret += $logEntry->isDeleted( LogPage::DELETED_USER )
-                       ? [ 'userhidden' => '' ]
-                       : [];
-               $ret += $logEntry->isDeleted( LogPage::DELETED_COMMENT )
-                       ? [ 'commenthidden' => '' ]
-                       : [];
-               $ret += $logEntry->isDeleted( LogPage::DELETED_ACTION )
-                       ? [ 'actionhidden' => '' ]
-                       : [];
 
                if ( LogEventsList::userCan( $this->row, LogPage::DELETED_ACTION, $user ) ) {
                        $ret['params'] = LogFormatter::newFromEntry( $logEntry )->formatParametersForApi();
index 7fff366..a9753b4 100644 (file)
@@ -188,10 +188,10 @@ class RevDelRevisionItem extends RevDelItem {
                $ret = [
                        'id' => $rev->getId(),
                        'timestamp' => wfTimestamp( TS_ISO_8601, $rev->getTimestamp() ),
+                       'userhidden' => (bool)$rev->isDeleted( Revision::DELETED_USER ),
+                       'commenthidden' => (bool)$rev->isDeleted( Revision::DELETED_COMMENT ),
+                       'texthidden' => (bool)$rev->isDeleted( Revision::DELETED_TEXT ),
                ];
-               $ret += $rev->isDeleted( Revision::DELETED_USER ) ? [ 'userhidden' => '' ] : [];
-               $ret += $rev->isDeleted( Revision::DELETED_COMMENT ) ? [ 'commenthidden' => '' ] : [];
-               $ret += $rev->isDeleted( Revision::DELETED_TEXT ) ? [ 'texthidden' => '' ] : [];
                if ( $rev->userCan( Revision::DELETED_USER, $user ) ) {
                        $ret += [
                                'userid' => $rev->getUser( Revision::FOR_THIS_USER ),
index a2a6760..3ee3ed5 100644 (file)
@@ -21,7 +21,7 @@ class DummySearchIndexFieldDefinition extends SearchIndexFieldDefinition {
                ];
 
                foreach ( $this->subfields as $subfield ) {
-                       $mapping['subfields'][] = $subfield->getMapping();
+                       $mapping['subfields'][] = $subfield->getMapping( $engine );
                }
 
                return $mapping;
index 90bfebd..0bcb07a 100644 (file)
@@ -104,7 +104,6 @@ abstract class SearchEngine {
         * @since 1.18
         * @param string $feature
         * @param mixed $data
-        * @return bool
         */
        public function setFeatureData( $feature, $data ) {
                $this->features[$feature] = $data;
index 69f2e49..575a9ac 100644 (file)
@@ -489,8 +489,10 @@ class SkinTemplate extends Skin {
                $tpl->set( 'debughtml', $this->generateDebugHTML() );
                $tpl->set( 'reporttime', wfReportTime() );
 
+               // Avoid PHP 7.1 warning of passing $this by reference
+               $skinTemplate = $this;
                // original version by hansm
-               if ( !Hooks::run( 'SkinTemplateOutputPageBeforeExec', [ &$this, &$tpl ] ) ) {
+               if ( !Hooks::run( 'SkinTemplateOutputPageBeforeExec', [ &$skinTemplate, &$tpl ] ) ) {
                        wfDebug( __METHOD__ . ": Hook SkinTemplateOutputPageBeforeExec broke outputPage execution!\n" );
                }
 
@@ -768,8 +770,10 @@ class SkinTemplate extends Skin {
                                MWNamespace::getSubject( $title->getNamespace() ) );
                }
 
+               // Avoid PHP 7.1 warning of passing $this by reference
+               $skinTemplate = $this;
                $result = [];
-               if ( !Hooks::run( 'SkinTemplateTabAction', [ &$this,
+               if ( !Hooks::run( 'SkinTemplateTabAction', [ &$skinTemplate,
                                $title, $message, $selected, $checkEdit,
                                &$classes, &$query, &$text, &$result ] ) ) {
                        return $result;
@@ -870,8 +874,10 @@ class SkinTemplate extends Skin {
 
                $userCanRead = $title->quickUserCan( 'read', $user );
 
+               // Avoid PHP 7.1 warning of passing $this by reference
+               $skinTemplate = $this;
                $preventActiveTabs = false;
-               Hooks::run( 'SkinTemplatePreventOtherActiveTabs', [ &$this, &$preventActiveTabs ] );
+               Hooks::run( 'SkinTemplatePreventOtherActiveTabs', [ &$skinTemplate, &$preventActiveTabs ] );
 
                // Checks if page is some kind of content
                if ( $title->canExist() ) {
@@ -1074,7 +1080,9 @@ class SkinTemplate extends Skin {
                                }
                        }
 
-                       Hooks::run( 'SkinTemplateNavigation', [ &$this, &$content_navigation ] );
+                       // Avoid PHP 7.1 warning of passing $this by reference
+                       $skinTemplate = $this;
+                       Hooks::run( 'SkinTemplateNavigation', [ &$skinTemplate, &$content_navigation ] );
 
                        if ( $userCanRead && !$wgDisableLangConversion ) {
                                $pageLang = $title->getPageLanguage();
@@ -1116,12 +1124,16 @@ class SkinTemplate extends Skin {
                                'context' => 'subject'
                        ];
 
+                       // Avoid PHP 7.1 warning of passing $this by reference
+                       $skinTemplate = $this;
                        Hooks::run( 'SkinTemplateNavigation::SpecialPage',
-                               [ &$this, &$content_navigation ] );
+                               [ &$skinTemplate, &$content_navigation ] );
                }
 
+               // Avoid PHP 7.1 warning of passing $this by reference
+               $skinTemplate = $this;
                // Equiv to SkinTemplateContentActions
-               Hooks::run( 'SkinTemplateNavigation::Universal', [ &$this, &$content_navigation ] );
+               Hooks::run( 'SkinTemplateNavigation::Universal', [ &$skinTemplate, &$content_navigation ] );
 
                // Setup xml ids and tooltip info
                foreach ( $content_navigation as $section => &$links ) {
@@ -1254,9 +1266,11 @@ class SkinTemplate extends Skin {
                                ];
                        }
 
+                       // Avoid PHP 7.1 warning of passing $this by reference
+                       $skinTemplate = $this;
                        // Use the copy of revision ID in case this undocumented, shady hook tries to mess with internals
                        Hooks::run( 'SkinTemplateBuildNavUrlsNav_urlsAfterPermalink',
-                               [ &$this, &$nav_urls, &$revid, &$revid ] );
+                               [ &$skinTemplate, &$nav_urls, &$revid, &$revid ] );
                }
 
                if ( $out->isArticleRelated() ) {
index bdf7638..fbc3022 100644 (file)
@@ -198,9 +198,7 @@ abstract class AuthManagerSpecialPage extends SpecialPage {
         * @param string $subPage Subpage of the special page.
         * @return string an AuthManager::ACTION_* constant.
         */
-       protected function getDefaultAction( $subPage ) {
-               throw new BadMethodCallException( 'Subclass did not implement getDefaultAction' );
-       }
+       abstract protected function getDefaultAction( $subPage );
 
        /**
         * Return custom message key.
index 2936754..5c8b3a6 100644 (file)
@@ -206,7 +206,7 @@ class DeletedContributionsPage extends SpecialPage {
                        ],
                ];
 
-               $form = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
+               HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
                        ->setWrapperLegendMsg( 'sp-contributions-search' )
                        ->setSubmitTextMsg( 'sp-contributions-submit' )
                        // prevent setting subpage and 'target' parameter at the same time
index c61609d..d8a468f 100644 (file)
@@ -119,7 +119,7 @@ class MIMEsearchPage extends QueryPage {
                        ],
                ];
 
-               $form = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
+               HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
                        ->setWrapperLegendMsg( 'mimesearch' )
                        ->setSubmitTextMsg( 'ilsubmit' )
                        ->setAction( $this->getPageTitle()->getLocalURL() )
index e11977f..1cb6549 100644 (file)
@@ -339,7 +339,7 @@ class MediaStatisticsPage extends QueryPage {
         * we need to implement since abstract in parent class.
         *
         * @param Skin $skin
-        * @param stdObject $result Result row
+        * @param stdClass $result Result row
         * @return bool|string|void
         * @throws MWException
         */
index 077a5d2..9e3a750 100644 (file)
@@ -108,7 +108,7 @@ class SpecialNewFiles extends IncludableSpecialPage {
                        unset( $formDescriptor['hidepatrolled'] );
                }
 
-               $form = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
+               HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
                        ->setWrapperLegendMsg( 'newimages-legend' )
                        ->setSubmitTextMsg( 'ilsubmit' )
                        ->setMethod( 'get' )
index 8530eb1..1ce61e3 100644 (file)
@@ -91,6 +91,8 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $opts->add( 'categories_any', false );
                $opts->add( 'tagfilter', '' );
 
+               $opts->add( 'userExpLevel', 'all' );
+
                return $opts;
        }
 
@@ -240,6 +242,8 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                        $opts['tagfilter']
                );
 
+               $this->filterOnUserExperienceLevel( $tables, $conds, $join_conds, $opts );
+
                if ( !$this->runMainQueryHook( $tables, $fields, $conds, $query_options, $join_conds,
                        $opts )
                ) {
@@ -803,4 +807,65 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                return 60 * 5;
        }
 
+       function filterOnUserExperienceLevel( &$tables, &$conds, &$join_conds, $opts ) {
+               global $wgLearnerEdits,
+                          $wgExperiencedUserEdits,
+                          $wgLearnerMemberSince,
+                          $wgExperiencedUserMemberSince;
+
+               $selectedExpLevels = explode( ',', strtolower( $opts['userExpLevel'] ) );
+               // remove values that are not recognized
+               $selectedExpLevels = array_intersect(
+                       $selectedExpLevels,
+                       [ 'newcomer', 'learner', 'experienced' ]
+               );
+               sort( $selectedExpLevels );
+
+               if ( $selectedExpLevels ) {
+                       $tables[] = 'user';
+                       $join_conds['user'] = [ 'LEFT JOIN', 'rc_user = user_id' ];
+
+                       $now = time();
+                       $secondsPerDay = 86400;
+                       $learnerCutoff = $now - $wgLearnerMemberSince * $secondsPerDay;
+                       $experiencedUserCutoff = $now - $wgExperiencedUserMemberSince * $secondsPerDay;
+
+                       $aboveNewcomer = $this->getDB()->makeList(
+                               [
+                                       'user_editcount >= ' . intval( $wgLearnerEdits ),
+                                       'user_registration <= ' . $this->getDB()->timestamp( $learnerCutoff ),
+                               ],
+                               IDatabase::LIST_AND
+                       );
+
+                       $aboveLearner = $this->getDB()->makeList(
+                               [
+                                       'user_editcount >= ' . intval( $wgExperiencedUserEdits ),
+                                       'user_registration <= ' . $this->getDB()->timestamp( $experiencedUserCutoff ),
+                               ],
+                               IDatabase::LIST_AND
+                       );
+
+                       if ( $selectedExpLevels === [ 'newcomer' ] ) {
+                               $conds[] =  "NOT ( $aboveNewcomer )";
+                       } elseif ( $selectedExpLevels === [ 'learner' ] ) {
+                               $conds[] = $this->getDB()->makeList(
+                                       [ $aboveNewcomer, "NOT ( $aboveLearner )" ],
+                                       IDatabase::LIST_AND
+                               );
+                       } elseif ( $selectedExpLevels === [ 'experienced' ] ) {
+                               $conds[] = $aboveLearner;
+                       } elseif ( $selectedExpLevels === [ 'learner', 'newcomer' ] ) {
+                               $conds[] = "NOT ( $aboveLearner )";
+                       } elseif ( $selectedExpLevels === [ 'experienced', 'newcomer' ] ) {
+                               $conds[] = $this->getDB()->makeList(
+                                       [ "NOT ( $aboveNewcomer )", $aboveLearner ],
+                                       IDatabase::LIST_OR
+                               );
+                       } elseif ( $selectedExpLevels === [ 'experienced', 'learner' ] ) {
+                               $conds[] = $aboveNewcomer;
+                       }
+               }
+       }
+
 }
index e1e2049..761610e 100644 (file)
@@ -41,14 +41,10 @@ class SpecialRunJobs extends UnlistedSpecialPage {
        public function execute( $par = '' ) {
                $this->getOutput()->disable();
                if ( wfReadOnly() ) {
-                       // HTTP 423 Locked
-                       HttpStatus::header( 423 );
-                       print 'Wiki is in read-only mode';
-
+                       wfHttpError( 423, 'Locked', 'Wiki is in read-only mode.' );
                        return;
                } elseif ( !$this->getRequest()->wasPosted() ) {
-                       HttpStatus::header( 400 );
-                       print 'Request must be POSTed';
+                       wfHttpError( 400, 'Bad Request', 'Request must be POSTed.' );
                        return;
                }
 
@@ -58,8 +54,9 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                $params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional );
                $missing = array_diff_key( $required, $params );
                if ( count( $missing ) ) {
-                       HttpStatus::header( 400 );
-                       print 'Missing parameters: ' . implode( ', ', array_keys( $missing ) );
+                       wfHttpError( 400, 'Bad Request',
+                               'Missing parameters: ' . implode( ', ', array_keys( $missing ) )
+                       );
                        return;
                }
 
@@ -71,8 +68,7 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                $verified = is_string( $providedSignature )
                        && hash_equals( $correctSignature, $providedSignature );
                if ( !$verified || $params['sigexpiry'] < time() ) {
-                       HttpStatus::header( 400 );
-                       print 'Invalid or stale signature provided';
+                       wfHttpError( 400, 'Bad Request', 'Invalid or stale signature provided.' );
                        return;
                }
 
index f7e46cb..aabd450 100644 (file)
@@ -209,7 +209,9 @@ class SpecialUpload extends SpecialPage {
                        $this->processUpload();
                } else {
                        # Backwards compatibility hook
-                       if ( !Hooks::run( 'UploadForm:initial', [ &$this ] ) ) {
+                       // Avoid PHP 7.1 warning of passing $this by reference
+                       $upload = $this;
+                       if ( !Hooks::run( 'UploadForm:initial', [ &$upload ] ) ) {
                                wfDebug( "Hook 'UploadForm:initial' broke output of the upload form\n" );
 
                                return;
@@ -483,8 +485,9 @@ class SpecialUpload extends SpecialPage {
 
                        return;
                }
-
-               if ( !Hooks::run( 'UploadForm:BeforeProcessing', [ &$this ] ) ) {
+               // Avoid PHP 7.1 warning of passing $this by reference
+               $upload = $this;
+               if ( !Hooks::run( 'UploadForm:BeforeProcessing', [ &$upload ] ) ) {
                        wfDebug( "Hook 'UploadForm:BeforeProcessing' broke processing the file.\n" );
                        // This code path is deprecated. If you want to break upload processing
                        // do so by hooking into the appropriate hooks in UploadBase::verifyUpload
@@ -570,7 +573,9 @@ class SpecialUpload extends SpecialPage {
 
                // Success, redirect to description page
                $this->mUploadSuccessful = true;
-               Hooks::run( 'SpecialUploadComplete', [ &$this ] );
+               // Avoid PHP 7.1 warning of passing $this by reference
+               $upload = $this;
+               Hooks::run( 'SpecialUploadComplete', [ &$upload ] );
                $this->getOutput()->redirect( $this->mLocalFile->getTitle()->getFullURL() );
        }
 
index 1d9c057..df98f33 100644 (file)
@@ -76,6 +76,7 @@ class UserrightsPage extends SpecialPage {
        public function execute( $par ) {
                $user = $this->getUser();
                $request = $this->getRequest();
+               $session = $request->getSession();
                $out = $this->getOutput();
 
                if ( $par !== null ) {
@@ -103,7 +104,13 @@ class UserrightsPage extends SpecialPage {
                }
 
                // show a successbox, if the user rights was saved successfully
-               if ( $request->getCheck( 'success' ) && $this->mFetchedUser !== null ) {
+               if (
+                       $session->get( 'specialUserrightsSaveSuccess' ) &&
+                       $this->mFetchedUser !== null
+               ) {
+                       // Remove session data for the success message
+                       $session->remove( 'specialUserrightsSaveSuccess' );
+
                        $out->addModules( [ 'mediawiki.special.userrights' ] );
                        $out->addModuleStyles( 'mediawiki.notification.convertmessagebox.styles' );
                        $out->addHTML(
@@ -171,6 +178,9 @@ class UserrightsPage extends SpecialPage {
                                        $targetUser
                                );
 
+                               // Set session data for the success message
+                               $session->set( 'specialUserrightsSaveSuccess', 1 );
+
                                $out->redirect( $this->getSuccessURL() );
 
                                return;
@@ -184,7 +194,7 @@ class UserrightsPage extends SpecialPage {
        }
 
        function getSuccessURL() {
-               return $this->getPageTitle( $this->mTarget )->getFullURL( [ 'success' => 1 ] );
+               return $this->getPageTitle( $this->mTarget )->getFullURL();
        }
 
        /**
index 799961a..2dddac5 100644 (file)
@@ -22,7 +22,7 @@
  * MalformedTitleException is thrown when a TitleParser is unable to parse a title string.
  * @since 1.23
  */
-class MalformedTitleException extends Exception {
+class MalformedTitleException extends Exception implements ILocalizedException {
        private $titleText = null;
        private $errorMessage = null;
        private $errorMessageParameters = [];
@@ -72,4 +72,12 @@ class MalformedTitleException extends Exception {
        public function getErrorMessageParameters() {
                return $this->errorMessageParameters;
        }
+
+       /**
+        * @since 1.29
+        * @return Message
+        */
+       public function getMessageObject() {
+               return wfMessage( $this->getErrorMessage(), $this->getErrorMessageParameters() );
+       }
 }
index ea6ef30..96f8638 100644 (file)
@@ -775,7 +775,9 @@ abstract class UploadBase {
                                        User::IGNORE_USER_RIGHTS
                                );
                        }
-                       Hooks::run( 'UploadComplete', [ &$this ] );
+                       // Avoid PHP 7.1 warning of passing $this by reference
+                       $uploadBase = $this;
+                       Hooks::run( 'UploadComplete', [ &$uploadBase ] );
 
                        $this->postProcessUpload();
                }
index 449fc05..c0c2cb5 100644 (file)
@@ -63,6 +63,52 @@ class UploadFromChunks extends UploadFromFile {
                }
        }
 
+       /**
+        * {@inheritdoc}
+        */
+       public function tryStashFile( User $user, $isPartial = false ) {
+               try {
+                       $this->verifyChunk();
+               } catch ( UploadChunkVerificationException $e ) {
+                       return Status::newFatal( $e->msg );
+               }
+
+               return parent::tryStashFile( $user, $isPartial );
+       }
+
+       /**
+        * {@inheritdoc}
+        * @throws UploadChunkVerificationException
+        * @deprecated since 1.28 Use tryStashFile() instead
+        */
+       public function stashFile( User $user = null ) {
+               wfDeprecated( __METHOD__, '1.28' );
+               $this->verifyChunk();
+               return parent::stashFile( $user );
+       }
+
+       /**
+        * {@inheritdoc}
+        * @throws UploadChunkVerificationException
+        * @deprecated since 1.28
+        */
+       public function stashFileGetKey() {
+               wfDeprecated( __METHOD__, '1.28' );
+               $this->verifyChunk();
+               return parent::stashFileGetKey();
+       }
+
+       /**
+        * {@inheritdoc}
+        * @throws UploadChunkVerificationException
+        * @deprecated since 1.28
+        */
+       public function stashSession() {
+               wfDeprecated( __METHOD__, '1.28' );
+               $this->verifyChunk();
+               return parent::stashSession();
+       }
+
        /**
         * Calls the parent doStashFile and updates the uploadsession table to handle "chunks"
         *
@@ -74,7 +120,6 @@ class UploadFromChunks extends UploadFromFile {
                $this->mChunkIndex = 0;
                $this->mOffset = 0;
 
-               $this->verifyChunk();
                // Create a local stash target
                $this->mStashFile = parent::doStashFile( $user );
                // Update the initial file offset (based on file size)
@@ -113,7 +158,7 @@ class UploadFromChunks extends UploadFromFile {
 
        /**
         * Append the final chunk and ready file for parent::performUpload()
-        * @return FileRepoStatus
+        * @return Status
         */
        public function concatenateChunks() {
                $chunkIndex = $this->getChunkIndex();
@@ -313,7 +358,7 @@ class UploadFromChunks extends UploadFromFile {
         *
         * @param string $chunkPath
         * @throws UploadChunkFileException
-        * @return FileRepoStatus
+        * @return Status
         */
        private function outputChunk( $chunkPath ) {
                // Key is fileKey + chunk index
index f1742b3..663c5da 100644 (file)
@@ -1643,16 +1643,20 @@ class User implements IDBAccessObject {
                if ( !$block instanceof Block && $ip !== null && !in_array( $ip, $wgProxyWhitelist ) ) {
                        // Local list
                        if ( self::isLocallyBlockedProxy( $ip ) ) {
-                               $block = new Block;
-                               $block->setBlocker( wfMessage( 'proxyblocker' )->text() );
-                               $block->mReason = wfMessage( 'proxyblockreason' )->text();
-                               $block->setTarget( $ip );
+                               $block = new Block( [
+                                       'byText' => wfMessage( 'proxyblocker' )->text(),
+                                       'reason' => wfMessage( 'proxyblockreason' )->text(),
+                                       'address' => $ip,
+                                       'systemBlock' => 'proxy',
+                               ] );
                                $this->blockTrigger = 'proxy-block';
                        } elseif ( $this->isAnon() && $this->isDnsBlacklisted( $ip ) ) {
-                               $block = new Block;
-                               $block->setBlocker( wfMessage( 'sorbs' )->text() );
-                               $block->mReason = wfMessage( 'sorbsreason' )->text();
-                               $block->setTarget( $ip );
+                               $block = new Block( [
+                                       'byText' => wfMessage( 'sorbs' )->text(),
+                                       'reason' => wfMessage( 'sorbsreason' )->text(),
+                                       'address' => $ip,
+                                       'systemBlock' => 'dnsbl',
+                               ] );
                                $this->blockTrigger = 'openproxy-block';
                        }
                }
@@ -1776,21 +1780,22 @@ class User implements IDBAccessObject {
                }
 
                if ( !is_array( $wgProxyList ) ) {
-                       // Load from the specified file
+                       // Load values from the specified file
                        $wgProxyList = array_map( 'trim', file( $wgProxyList ) );
                }
 
-               if ( !is_array( $wgProxyList ) ) {
-                       $ret = false;
-               } elseif ( array_search( $ip, $wgProxyList ) !== false ) {
-                       $ret = true;
-               } elseif ( array_key_exists( $ip, $wgProxyList ) ) {
-                       // Old-style flipped proxy list
-                       $ret = true;
-               } else {
-                       $ret = false;
+               if ( is_array( $wgProxyList ) ) {
+                       if (
+                               // Look for IP as value
+                               array_search( $ip, $wgProxyList ) !== false ||
+                               // Look for IP as key (for backwards-compatility)
+                               array_key_exists( $ip, $wgProxyList )
+                       ) {
+                               return true;
+                       }
                }
-               return $ret;
+
+               return false;
        }
 
        /**
@@ -2067,8 +2072,10 @@ class User implements IDBAccessObject {
 
                if ( $blocked && $block === null ) {
                        // back-compat: UserIsBlockedGlobally didn't have $block param first
-                       $block = new Block;
-                       $block->setTarget( $ip );
+                       $block = new Block( [
+                               'address' => $ip,
+                               'systemBlock' => 'global-block'
+                       ] );
                }
 
                $this->mGlobalBlock = $blocked ? $block : false;
@@ -2477,24 +2484,6 @@ class User implements IDBAccessObject {
                return $this->mTouched;
        }
 
-       /**
-        * @deprecated Removed in 1.27.
-        * @return Password
-        * @since 1.24
-        */
-       public function getPassword() {
-               throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
-       }
-
-       /**
-        * @deprecated Removed in 1.27.
-        * @return Password
-        * @since 1.24
-        */
-       public function getTemporaryPassword() {
-               throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
-       }
-
        /**
         * Set the password and reset the random token.
         * Calls through to authentication plugin if necessary;
@@ -2662,16 +2651,6 @@ class User implements IDBAccessObject {
                throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
        }
 
-       /**
-        * Has password reminder email been sent within the last
-        * $wgPasswordReminderResendTime hours?
-        * @deprecated Removed in 1.27. See above.
-        * @return bool
-        */
-       public function isPasswordReminderThrottled() {
-               throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
-       }
-
        /**
         * Get the user's e-mail address
         * @return string User's email address
index 2e4ef89..ac8d4cb 100644 (file)
@@ -45,7 +45,9 @@ class Language {
        public $dateFormatStrings = [];
        public $mExtendedSpecialPageAliases;
 
-       protected $namespaceNames, $mNamespaceIds, $namespaceAliases;
+       /** @var array|null */
+       protected $namespaceNames;
+       protected $mNamespaceIds, $namespaceAliases;
 
        /**
         * ReplacementArray object caches
@@ -463,10 +465,11 @@ class Language {
                if ( is_null( $this->namespaceNames ) ) {
                        global $wgMetaNamespace, $wgMetaNamespaceTalk, $wgExtraNamespaces;
 
-                       $this->namespaceNames = self::$dataCache->getItem( $this->mCode, 'namespaceNames' );
                        $validNamespaces = MWNamespace::getCanonicalNamespaces();
 
-                       $this->namespaceNames = $wgExtraNamespaces + $this->namespaceNames + $validNamespaces;
+                       $this->namespaceNames = $wgExtraNamespaces +
+                               self::$dataCache->getItem( $this->mCode, 'namespaceNames' );
+                       $this->namespaceNames += $validNamespaces;
 
                        $this->namespaceNames[NS_PROJECT] = $wgMetaNamespace;
                        if ( $wgMetaNamespaceTalk ) {
@@ -2577,7 +2580,7 @@ class Language {
 
        /**
         * @param string $key
-        * @return array|null
+        * @return string|null
         */
        public function getMessage( $key ) {
                return self::$dataCache->getSubitem( $this->mCode, 'messages', $key );
@@ -3734,6 +3737,43 @@ class Language {
                        return $wgGrammarForms[$this->getCode()][$case][$word];
                }
 
+               $grammarTransformations = $this->getGrammarTransformations();
+
+               if ( isset( $grammarTransformations[$case] ) ) {
+                       $forms = $grammarTransformations[$case];
+
+                       // Some names of grammar rules are aliases for other rules.
+                       // In such cases the value is a string rather than object,
+                       // so load the actual rules.
+                       if ( is_string( $forms ) ) {
+                               $forms = $grammarTransformations[$forms];
+                       }
+
+                       foreach ( array_values( $forms ) as $rule ) {
+                               $form = $rule[0];
+
+                               if ( $form === '@metadata' ) {
+                                       continue;
+                               }
+
+                               $replacement = $rule[1];
+
+                               $regex = '/' . addcslashes( $form, '/' ) . '/u';
+                               $patternMatches = preg_match( $regex, $word );
+
+                               if ( $patternMatches === false ) {
+                                       wfLogWarning(
+                                               'An error occurred while processing grammar. ' .
+                                               "Word: '$word'. Regex: /$form/."
+                                       );
+                               } elseif ( $patternMatches === 1 ) {
+                                       $word = preg_replace( $regex, $replacement, $word );
+
+                                       break;
+                               }
+                       }
+               }
+
                return $word;
        }
 
index 5a9f652..06fec44 100644 (file)
@@ -415,8 +415,6 @@ class LanguageConverter {
                                                $attr = $this->recursiveConvertTopLevel( $attr, $toVariant );
                                        }
 
-                                       // Remove HTML tags to avoid disrupting the layout
-                                       $attr = preg_replace( '/<[^>]+>/', '', $attr );
                                        if ( $attr !== $attrs[$attrName] ) {
                                                $attrs[$attrName] = $attr;
                                                $changed = true;
diff --git a/languages/classes/LanguageHe.php b/languages/classes/LanguageHe.php
deleted file mode 100644 (file)
index a6aaf6d..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-<?php
-/**
- * Hebrew (עברית) specific code.
- *
- * 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
- * @author Rotem Liss
- * @ingroup Language
- */
-
-/**
- * Hebrew (עברית)
- *
- * @ingroup Language
- */
-class LanguageHe extends Language {
-
-       /**
-        * Convert grammar forms of words.
-        *
-        * Available cases:
-        * "prefixed" (or "תחילית") - when the word has a prefix
-        *
-        * @param string $word The word to convert
-        * @param string $case The case
-        *
-        * @return string
-        */
-       public function convertGrammar( $word, $case ) {
-               global $wgGrammarForms;
-               if ( isset( $wgGrammarForms['he'][$case][$word] ) ) {
-                       return $wgGrammarForms['he'][$case][$word];
-               }
-
-               switch ( $case ) {
-                       case 'prefixed':
-                       case 'תחילית':
-                               # Duplicate the "Waw" if prefixed, but not if it is already double.
-                               if ( substr( $word, 0, 2 ) === "ו" && substr( $word, 0, 4 ) !== "וו" ) {
-                                       $word = "ו" . $word;
-                               }
-
-                               # Remove the "He" article if prefixed.
-                               if ( substr( $word, 0, 2 ) === "ה" ) {
-                                       $word = substr( $word, 2 );
-                               }
-
-                               # Add a hyphen (maqaf) before non-Hebrew letters.
-                               if ( substr( $word, 0, 2 ) < "א" || substr( $word, 0, 2 ) > "ת" ) {
-                                       $word = "־" . $word;
-                               }
-               }
-
-               return $word;
-       }
-}
index 62de390..7b15721 100644 (file)
  * @ingroup Language
  */
 class LanguageRu extends Language {
-       /**
-        * Convert from the nominative form of a noun to some other case
-        * Invoked with {{grammar:case|word}}
-        *
-        * @param string $word
-        * @param string $case
-        * @return string
-        */
-       function convertGrammar( $word, $case ) {
-               global $wgGrammarForms;
-               if ( isset( $wgGrammarForms['ru'][$case][$word] ) ) {
-                       return $wgGrammarForms['ru'][$case][$word];
-               }
-
-               $grammarTransformations = $this->getGrammarTransformations();
-
-               if ( isset( $grammarTransformations[$case] ) ) {
-                       foreach ( array_values( $grammarTransformations[$case] ) as $rule ) {
-                               $form = $rule[0];
-
-                               if ( $form === '@metadata' ) {
-                                       continue;
-                               }
-
-                               $replacement = $rule[1];
-
-                               $regex = "/$form/";
-
-                               if ( preg_match( $regex, $word ) ) {
-                                       $word = preg_replace( $regex, $replacement, $word );
-
-                                       break;
-                               }
-                       }
-               }
-
-               return $word;
-       }
-
        /**
         * Four-digit number should be without group commas (spaces)
         * See manual of style at https://ru.wikipedia.org/wiki/Википедия:Оформление_статей
index 72bde40..a155d03 100644 (file)
  * @ingroup Language
  */
 class LanguageUk extends Language {
-
-       /**
-        * Convert from the nominative form of a noun to some other case
-        * Invoked with {{grammar:case|word}}
-        *
-        * @param string $word
-        * @param string $case
-        * @return string
-        */
-       function convertGrammar( $word, $case ) {
-               global $wgGrammarForms;
-               if ( isset( $wgGrammarForms['uk'][$case][$word] ) ) {
-                       return $wgGrammarForms['uk'][$case][$word];
-               }
-
-               # These rules don't cover the whole language.
-               # They are used only for site names.
-
-               # join and array_slice instead mb_substr
-               $ar = [];
-               preg_match_all( '/./us', $word, $ar );
-               if ( !preg_match( "/[a-zA-Z_]/us", $word ) ) {
-                       switch ( $case ) {
-                               case 'genitive': # родовий відмінок
-                                       if ( implode( '', array_slice( $ar[0], -2 ) ) === 'ія' ) {
-                                               $word = implode( '', array_slice( $ar[0], 0, -2 ) ) . 'ії';
-                                       } elseif ( implode( '', array_slice( $ar[0], -2 ) ) === 'ти' ) {
-                                               $word = implode( '', array_slice( $ar[0], 0, -2 ) ) . 'т';
-                                       } elseif ( implode( '', array_slice( $ar[0], -2 ) ) === 'ди' ) {
-                                               $word = implode( '', array_slice( $ar[0], 0, -2 ) ) . 'дів';
-                                       } elseif ( implode( '', array_slice( $ar[0], -3 ) ) === 'ник' ) {
-                                               $word = implode( '', array_slice( $ar[0], 0, -3 ) ) . 'ника';
-                                       }
-                                       break;
-                               case 'accusative': # знахідний відмінок
-                                       if ( implode( '', array_slice( $ar[0], -2 ) ) === 'ія' ) {
-                                               $word = implode( '', array_slice( $ar[0], 0, -2 ) ) . 'ію';
-                                       }
-                                       break;
-                       }
-               }
-               return $word;
-       }
-
        /**
         * Ukrainian numeric format is "12 345,67" but "1234,56"
         *
diff --git a/languages/data/grammarTransformations/he.json b/languages/data/grammarTransformations/he.json
new file mode 100644 (file)
index 0000000..50620b1
--- /dev/null
@@ -0,0 +1,26 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Rotem Liss",
+                       "Amir E. Aharoni (amir.aharoni@mail.huji.ac.il)"
+               ]
+       },
+       "prefixed": "תחילית",
+       "תחילית": [
+               [ "@metadata", [
+                       "comment", "הכפלת ו, מחיקת ה הידיעה, הוספת מקף"
+               ] ],
+               [
+                       "^(ו[^ו].+)$",
+                       "ו$1"
+               ],
+               [
+                       "ה(.+)$",
+                       "$1"
+               ],
+               [
+                       "^([^א-ת].+)$",
+                       "־$1"
+               ]
+       ]
+}
diff --git a/languages/data/grammarTransformations/uk.json b/languages/data/grammarTransformations/uk.json
new file mode 100644 (file)
index 0000000..6512225
--- /dev/null
@@ -0,0 +1,18 @@
+{
+       "@metadata": {
+               "authors": [
+                       "Gutsul",
+                       "Amir E. Aharoni (amir.aharoni@mail.huji.ac.il)"
+               ],
+               "comment": "These rules don't cover the whole grammar of the language, and are intended only for names of languages and Wikimedia projects."
+       },
+       "genitive": [
+               [ "(.+)ія$", "$1ії" ],
+               [ "(.+)ти$", "$1т" ],
+               [ "(.+)ди$", "$1дів" ],
+               [ "(.+)ник$", "$1ника" ]
+       ],
+       "accusative": [
+               [ "(.+)ія$", "$1ію" ]
+       ]
+}
index f6c6636..4ef5638 100644 (file)
        "rcshowhidebots": "$1 البوتات",
        "rcshowhidebots-show": "أظهر",
        "rcshowhidebots-hide": "أخف",
-       "rcshowhideliu": "$1 {{GENDER:$1|مستخدمين مسجلين|مستخدمات مسجلات|مستخدمون مسجلون}}",
+       "rcshowhideliu": "$1 المستخدمين المسجلين",
        "rcshowhideliu-show": "أظهر",
        "rcshowhideliu-hide": "أخف",
        "rcshowhideanons": "$1 المستخدمين المجهولين",
        "modifiedarticleprotection": "غير مستوى حماية \"[[$1]]\"",
        "unprotectedarticle": "أزال الحماية من \"[[$1]]\"",
        "movedarticleprotection": "نقل إعدادات الحماية من \"[[$2]]\" إلى \"[[$1]]\"",
-       "protectedarticle-comment": "{{GENDER:$2|محمي}} \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|حمى}} \"[[$1]]\"",
        "modifiedarticleprotection-comment": "{{GENDER:$2|غير مستوى الحماية|غيرت مستوى الحماية}} ل\"[[$1]]\"",
        "unprotectedarticle-comment": "{{GENDER:$2|أزال الحماية|أزالت الحماية}} من \"[[$1]]\"",
        "protect-title": "ضبط حماية \"$1\"",
        "pageinfo-length": "حجم الصفحة (بالبايت)",
        "pageinfo-article-id": "معرف الصفحة (ID)",
        "pageinfo-language": "لغة محتوى الصفحة",
+       "pageinfo-language-change": "غير",
        "pageinfo-content-model": "نموذج محتوى الصفحة",
        "pageinfo-content-model-change": "تغيير",
        "pageinfo-robot-policy": "فهرسة الروبوتات",
        "log-action-filter-newusers": "نوع إنشاء الحساب:",
        "log-action-filter-patrol": "نوع الخفر:",
        "log-action-filter-protect": "نوع الحماية:",
-       "log-action-filter-rights": "نوع تغيير الصلاحية",
+       "log-action-filter-rights": "نوع تغيير الصلاحية:",
        "log-action-filter-suppress": "نوع الإخفاء:",
        "log-action-filter-upload": "نوع الرفع:",
        "log-action-filter-all": "الكل",
        "restrictionsfield-badip": "عنوان أيبي أو نطاق غير صحيح: $1",
        "restrictionsfield-label": "نطاقات الأيبي المسموح بها:",
        "restrictionsfield-help": "عنوان أيبي أو نطاق CIDR واحد لكل سطر. لتفعيل كل شيء، استخدم<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "المراجعة $1",
        "pageid": "معرف الصفحة $1"
 }
index b649c2d..b61e8bf 100644 (file)
        "blockedtitle": "Удзельнік заблякаваны",
        "blockedtext": "<strong>Ваш рахунак удзельніка ці IP-адрас быў заблякаваны.</strong>\n\nБлякаваньне выканаў $1.\nПрычына гэтага: <em>$2</em>.\n\n* Пачатак блякаваньня: $8\n* Сканчэньне блякаваньня: $6\n* Быў заблякаваны: $7\n\nВы можаце скантактавацца з $1 ці адным зь іншых [[{{MediaWiki:Grouppage-sysop}}|адміністратараў]], каб абмеркаваць блякаваньне. Заўважце, што Вы ня зможаце ўжыць магчымасьць «даслаць ліст па электроннай пошце», пакуль не пазначыце сапраўдны адрас электроннай пошты ў Вашых [[Special:Preferences|наладах]], і калі гэта Вам не было забаронена.\nВаш IP-адрас — $3, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што Вы будзеце рабіць.",
        "autoblockedtext": "Ваш IP-адрас быў аўтаматычна заблякаваны, таму што ён ужываўся іншым удзельнікам, які быў заблякаваны $1.\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, ідэнтыфікатар блякаваньня — #$5.\nКалі ласка, улучайце ўсю вышэйпададзеную інфармацыю ва ўсе запыты, што Вы будзеце рабіць.",
+       "systemblockedtext": "Вашае імя ўдзельніка ці IP-адрас былі аўтаматычна заблякаваныя MediaWiki.\nЗ наступнай прычыны:\n\n:<em>$2</em>\n\n* Пачатак блякаваньня: $8\n* Сканчэньне блякаваньня: $6\n* Мэта блякаваньня: $7\n\nВаш цяперашні IP-адрас — $3.\nКалі ласка, уключайце ўсе пададзеныя вышэй дэталі ва ўсе запыты, што вы робіце.",
        "blockednoreason": "прычына не пазначана",
        "whitelistedittext": "Вам трэба $1, каб рэдагаваць старонкі.",
        "confirmedittext": "Вы мусіце пацьвердзіць Ваш адрас электроннай пошты перад рэдагаваньнем старонак. Калі ласка, пазначце і пацьвердзіце адрас электроннай пошты праз Вашы [[Special:Preferences|налады]].",
        "nocreatetext": "У {{GRAMMAR:месны|{{SITENAME}}}} абмежаванае стварэньне новых старонак.\nВы можаце вярнуцца і рэдагаваць існую старонку, альбо [[Special:UserLogin|ўвайсьці ў сыстэму ці стварыць рахунак]].",
        "nocreate-loggedin": "Вы ня маеце дазволу на стварэньне новых старонак.",
        "sectioneditnotsupported-title": "Рэдагаваньне сэкцыяў не падтрымліваецца",
-       "sectioneditnotsupported-text": "Рэдагаваньне сэкцыяў не падтрымліваецца ў гэтай старонцы рэдагаваньня",
+       "sectioneditnotsupported-text": "Рэдагаваньне сэкцыяў не падтрымліваецца на гэтай старонцы.",
        "permissionserrors": "Памылка дазволу",
        "permissionserrorstext": "Вы ня маеце дазволу на гэтае дзеяньне з {{PLURAL:$1|1=наступнай прычыны|наступных прычынаў}}:",
        "permissionserrorstext-withaction": "Вы ня маеце дазволу на $2 з {{PLURAL:$1|1=наступнай прычыны|наступных прычынаў}}:",
        "contentmodelediterror": "Вы ня можаце рэдагаваць гэтую вэрсію, бо яе мадэль зьместу — <code>$1</code>, якая адрозьніваецца ад цяперашняй мадэлі зьместу старонкі — <code>$2</code>.",
-       "recreate-moveddeleted-warn": "'''Увага: Вы ствараеце старонку, якая раней была выдаленая.'''\n\nУпэўніцеся, што стварэньне гэтай старонкі неабходнае.\nНіжэй пададзеныя журналы выдаленьняў і пераносаў гэтай старонкі:",
+       "recreate-moveddeleted-warn": "<strong>Увага: вы ствараеце старонку, якая раней была выдаленая.</strong>\n\nУпэўніцеся, што стварэньне гэтай старонкі неабходнае.\nНіжэй пададзеныя журналы выдаленьняў і пераносаў гэтай старонкі:",
        "moveddeleted-notice": "Гэта старонка была выдаленая. Журналы выдаленьняў і пераносаў для гэтай старонкі пададзеныя ніжэй.",
        "moveddeleted-notice-recent": "Выбачайце, гэтая старонка была нядаўна выдаленая (цягам апошніх 24 гадзінаў).\nЖурналы выдаленьняў і пераносаў для гэтай старонкі пададзеныя ніжэй для даведкі.",
        "log-fulllog": "Паказаць журнал цалкам",
        "pageinfo-length": "Памер старонкі (у байтах)",
        "pageinfo-article-id": "Ідэнтыфікатар старонкі",
        "pageinfo-language": "Мова зьместу старонкі",
+       "pageinfo-language-change": "зьмяніць",
        "pageinfo-content-model": "Мадэль зьместу старонкі",
        "pageinfo-content-model-change": "зьмяніць",
        "pageinfo-robot-policy": "Індэксацыя пашукавікамі",
        "log-action-filter-contentmodel-change": "Зьмена мадэлі зьместу",
        "log-action-filter-contentmodel-new": "Стварэньне старонкі зь нестандартнай мадэльлю зьместу",
        "log-action-filter-delete-delete": "Выдаленьне старонкі",
+       "log-action-filter-delete-delete_redir": "Перазапіс перанакіраваньня",
        "log-action-filter-delete-restore": "Аднаўленьне старонкі",
        "log-action-filter-delete-event": "Выдаленьне журналу",
        "log-action-filter-delete-revision": "Выдаленьне вэрсіі",
        "log-action-filter-patrol-patrol": "Ручное патруляваньне",
        "log-action-filter-patrol-autopatrol": "Аўтаматычнае патруляваньне",
        "log-action-filter-protect-protect": "Абарона",
+       "log-action-filter-protect-modify": "Зьмена абароны",
        "log-action-filter-protect-unprotect": "Зьняцьце абароны",
+       "log-action-filter-protect-move_prot": "Перанос абароны",
+       "log-action-filter-rights-rights": "Ручная зьмена",
        "log-action-filter-rights-autopromote": "Аўтаматычнае зьмяненьне",
+       "log-action-filter-suppress-event": "Утойваньне журнала",
+       "log-action-filter-suppress-revision": "Утойваньне вэрсіі",
+       "log-action-filter-suppress-delete": "Утойваньне старонкі",
+       "log-action-filter-suppress-block": "Утойваньне ўдзельніка праз блякаваньне",
+       "log-action-filter-suppress-reblock": "Утойваньне ўдзельніка праз паўторнае блякаваньне",
        "log-action-filter-upload-upload": "Новая загрузка",
+       "log-action-filter-upload-overwrite": "Паўторная загрузка",
+       "authmanager-authn-not-in-progress": "Аўтэнтыфікацыя не выконваецца або страчаныя зьвесткі пра сэсію. Калі ласка, пачніце зноў з самага пачатку.",
        "authmanager-realname-label": "Сапраўднае імя",
        "authmanager-provider-temporarypassword": "Часовы пароль",
        "changecredentials": "Зьмена ўліковых зьвестак",
index 571c340..f94406c 100644 (file)
        "sp-contributions-newbies-sub": "З новых рахункаў",
        "sp-contributions-newbies-title": "Уклады ўдзельнікаў з новых рахункаў",
        "sp-contributions-blocklog": "блакіроўкі",
-       "sp-contributions-suppresslog": "заглушаны ўклад удзельніка",
-       "sp-contributions-deleted": "сцёрты ўклад удзельніка",
+       "sp-contributions-suppresslog": "схаваны ўклад {{GENDER:$1|удзельніка|удзельніцы}}",
+       "sp-contributions-deleted": "сцёрты ўклад {{GENDER:$1|удзельніка|удзельніцы}}",
        "sp-contributions-uploads": "укладанні",
        "sp-contributions-logs": "журналы",
        "sp-contributions-talk": "размовы",
        "log-action-filter-protect-move_prot": "Ахова старонкі",
        "log-action-filter-rights-rights": "Ручное змяненне",
        "log-action-filter-rights-autopromote": "Аўтаматычнае змяненне",
+       "log-action-filter-suppress-event": "Cкрыванне журнала",
+       "log-action-filter-suppress-revision": "Скрыванне версіі",
+       "log-action-filter-suppress-delete": "Cкрыванне старонкі",
        "log-action-filter-upload-upload": "Новая перадача",
        "log-action-filter-upload-overwrite": "Выкладванне",
        "authmanager-authn-not-in-progress": "Праверка сапраўднасці не выконваецца або сесія перадачы дадзеных была страчана. Калі ласка, пачніце зноў з самага пачатку.",
index 1b5efad..b1f4e98 100644 (file)
        "nosuchaction": "এমন কোন কাজ নেই",
        "nosuchactiontext": "এই উআরএল এ নির্ধারিত কাজটি অবৈধ।\nআপনি হয়তো একটি ভুল লিঙ্ক দিয়েছেন অথবা ইউআরএল লিখতে ভুল করেছেন।\nএটি এমনও নির্দেশ করে যে {{SITENAME}} সাইটে ব্যবহৃত সফটওয়্যারটিতে একটি ত্রুটি রয়েছে।",
        "nosuchspecialpage": "এমন কোন বিশেষ পাতা নেই",
-       "nospecialpagetext": "<strong>আপনি একটি অবৈধ বিশেষ পাতা অনুরোধ করেছেন।</strong>\n\n[[Special:SpecialPages|{{int:specialpages}}]]-এ বৈধ বিশেষ পাতাগুলির একটি তালিকা পাবেন।",
+       "nospecialpagetext": "<strong>আপনি একটি অবৈধ বিশেষ পাতা অনুরোধ করেছেন।</strong>\n\n[[Special:SpecialPages|{{int:specialpages}}]]-এ বৈধ বিশেষ পাতাগুলির একটি তালিকা পাবেন।",
        "error": "ত্রুটি",
        "databaseerror": "ডাটাবেস ত্রুটি",
        "databaseerror-text": "ডাটাবেজ অনুসন্ধান ত্রুটি।\nএটি সফটওয়্যারের একটি ত্রুটি হতে পারে।",
        "previewerrortext": "আপনার পরিবর্তনগুলি প্রাকদর্শন করার চেষ্টা করার সময় একটি ত্রুটি ঘটেছে।",
        "blockedtitle": "ব্যবহারকারীকে বাধা দেয়া হয়েছে",
        "blockedtext": "আপনার ব্যবহারকারী নাম বা আইপি ঠিকানার ঊপর নিষেধাজ্ঞা আরোপিত হয়েছে।\n\n$1 নিষেধাজ্ঞা আরোপ করেছেন। নিষেধের কারণ হিসেবে বলা হয়েছে:''$2''।\n\n* নিষেধাজ্ঞা শুরুর সময়:$8\n* নিষেধাজ্ঞা উঠিয়ে নেয়ার সময়: $6\n* যার উপর নিষেধাজ্ঞা আরোপ করা হয়েছে: $7\n\nআপনি $1 অথবা [[{{MediaWiki:Grouppage-sysop}}|প্রশাসকদের]] কারও সাথে এই নিষেধাজ্ঞা সংক্রান্ত বিষয়ে আলোচনা করতে পারেন।\n\nআপনি '(ব্যবহারকারীকে) ইমেইল করুন' ফিচারটি ব্যবহার করতে পারবেন না। তবে [[Special:Preferences|আপনার পছন্দ তালিকাতে]] যদি একটি বৈধ ই-মেইল ঠিকানা নির্দিষ্ট করা হয়ে থাকে এবং ফিচারটি ব্যবহারে যদি আপনাকে বাধা না দেওয়া হয়ে থাকে, তবে আপনি ফিচারটি ব্যবহার করতে পারবেন।\n\nআপনার বর্তমান আইপি ঠিকানা $3, এবং আপনার নিষেধাজ্ঞা নং হল #$5।\n\nদয়া করে আপনার যেকোন জিজ্ঞাসাতে উপরের সমস্ত বিবরণ অন্তর্ভুক্ত করুন।",
-       "autoblockedtext": "à¦\86পনার à¦\86à¦\87পি à¦ à¦¿à¦\95ানাà¦\95à§\87 à¦¸à§\8dবয়à¦\82à¦\95à§\8dরিয়ভাবà§\87 à¦¬à¦¾à¦§à¦¾ à¦¦à§\87য়া à¦¹à¦¯à¦¼à§\87à¦\9bà§\87 à¦\95ারণ à¦\8fà¦\95à¦\87 à¦\86à¦\87পি à¦ à¦¿à¦\95ানার à¦\86রà§\87à¦\95à¦\9cন à¦¬à§\8dযবহারà¦\95ারà§\80 à¦¬à§\8dযবহার à¦\95রà¦\9bà§\87ন à¦¯à¦¾à¦\95à§\87 $1  à¦¦à§\8dবারা à¦¬à¦¾à¦§à¦¾ à¦¦à§\87à¦\93য়া à¦¹à¦¯à¦¼à§\87à¦\9bà§\87।\nবাধাদানà§\87র à¦¯à§\87 à¦\95ারণ à¦¦à§\87য়া à¦¹à¦¯à¦¼à§\87à¦\9bà§\87:\n\n:''$2''\n\n* à¦¬à¦¾à¦§à¦¾ à¦¶à§\81রà§\81র à¦¸à¦®à¦¯à¦¼: $8\n* à¦¬à¦¾à¦§à¦¾ à¦¶à§\87ষà§\87র à¦¸à¦®à¦¯à¦¼: $6\n* à¦¯à¦¾à¦\95à§\87 à¦¬à¦¾à¦§à¦¾ à¦¦à§\87à¦\93য়ার à¦\9aà§\87ষà§\8dà¦\9fা à¦\95রা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87: $7\n\nà¦\86পনি $1-à¦\8fর à¦¸à¦¾à¦¥à§\87 à¦\95িà¦\82বা à¦\85নà§\8dয à¦¯à§\87à¦\95à§\8bন [[{{MediaWiki:Grouppage-sysop}}|পà§\8dরশাসà¦\95à§\87র]] à¦¸à¦¾à¦¥à§\87 à¦¯à§\8bà¦\97াযà§\8bà¦\97 à¦\95রà§\87 à¦¬à¦¾à¦§à¦¾à¦° à¦¬à§\8dযাপারà¦\9fি à¦\86লà§\8bà¦\9aনা à¦\95রতà§\87 à¦ªà¦¾à¦°à§\87ন।\n\nলà¦\95à§\8dষà§\8dয à¦\95রà§\81ন, à¦¯à¦¦à¦¿ à¦\86পনি \"à¦\8fà¦\87 à¦¬à§\8dযবহারà¦\95ারà§\80à¦\95à§\87 à¦\87-মà§\87à¦\87ল à¦\95রà§\81ন\" à¦«à¦¿à¦\9aারà¦\9fি à¦¬à§\8dযবহার à¦\95রতà§\87 à¦\9aান, à¦¤à¦¬à§\87 à¦\86পনার [[Special:Preferences|পà¦\9bনà§\8dদ]] à¦\85পশনà§\87 à¦\8fà¦\95à¦\9fি à¦¬à§\88ধ à¦\87মà§\87à¦\87ল à¦ à¦¿à¦\95ানা à¦¦à¦¿à¦¤à§\87 à¦¹à¦¬à§\87 à¦\8fবà¦\82 à¦\86পনার à¦¸à§\87à¦\9fি à¦¬à§\8dযবহারà§\87 à¦\95à§\8bন à¦¬à¦¾à¦§à¦¾ à¦¥à¦¾à¦\95তà§\87 à¦ªà¦¾à¦°à¦¬à§\87 à¦¨à¦¾à¥¤\n\nà¦\86পনার à¦¬à¦°à§\8dতমান IP à¦ à¦¿à¦\95ানা à¦¹à¦\9aà§\8dà¦\9bà§\87 $3, à¦\8fবà¦\82 à¦¯à¦¾ à¦¬à¦¾à¦§à¦¾ à¦¦à¦¾à¦¨à§\87র à¦\86à¦\87ডি à¦¹à¦² $5।\nযেকোন প্রশ্ন করার সময় উপরের সকল তথ্য উল্লেখ করুন।",
+       "autoblockedtext": "à¦\86পনার à¦\86à¦\87পি à¦ à¦¿à¦\95ানাà¦\95à§\87 à¦¸à§\8dবয়à¦\82à¦\95à§\8dরিয়ভাবà§\87 à¦¬à¦¾à¦§à¦¾ à¦¦à§\87য়া à¦¹à¦¯à¦¼à§\87à¦\9bà§\87 à¦\95ারণ à¦\8fà¦\9fি à¦\86রà§\87à¦\95à¦\9cন à¦¬à§\8dযবহারà¦\95ারà§\80 à¦¦à§\8dবারা à¦¬à§\8dযবহà§\83ত à¦¹à¦¯à¦¼à§\87à¦\9bà§\87, à¦¯à¦¾à¦\95à§\87 $1 à¦¬à¦¾à¦§à¦¾ à¦¦à¦¿à¦¯à¦¼à§\87à¦\9bà§\87ন।\nযà§\87 à¦\95ারণà§\87 à¦¬à¦¾à¦§à¦¾ à¦¦à§\87য়া à¦¹à¦¯à¦¼à§\87à¦\9bà§\87:\n\n:''$2''\n\n* à¦¬à¦¾à¦§à¦¾ à¦¶à§\81রà§\81র à¦¸à¦®à¦¯à¦¼: $8\n* à¦¬à¦¾à¦§à¦¾ à¦¶à§\87ষà§\87র à¦¸à¦®à¦¯à¦¼: $6\n* à¦¯à¦¾à¦\95à§\87 à¦¬à¦¾à¦§à¦¾ à¦¦à§\87à¦\93য়ার à¦\9aà§\87ষà§\8dà¦\9fা à¦\95রা à¦¹à¦¯à¦¼à§\87à¦\9bà§\87: $7\n\nà¦\86পনি $1-à¦\8fর à¦¸à¦¾à¦¥à§\87 à¦\95িà¦\82বা à¦\85নà§\8dয à¦¯à§\87à¦\95à§\8bন [[{{MediaWiki:Grouppage-sysop}}|পà§\8dরশাসà¦\95à§\87র]] à¦¸à¦¾à¦¥à§\87 à¦¯à§\8bà¦\97াযà§\8bà¦\97 à¦\95রà§\87 à¦¬à¦¾à¦§à¦¾à¦° à¦¬à§\8dযাপারà¦\9fি à¦\86লà§\8bà¦\9aনা à¦\95রতà§\87 à¦ªà¦¾à¦°à§\87ন।\n\nলà¦\95à§\8dষà§\8dয à¦\95রà§\81ন, à¦¯à¦¦à¦¿ à¦\86পনি \"à¦\8fà¦\87 à¦¬à§\8dযবহারà¦\95ারà§\80à¦\95à§\87 à¦\87-মà§\87à¦\87ল à¦\95রà§\81ন\" à¦¬à§\88শিষà§\8dà¦\9fà§\8dযà¦\9fি à¦¬à§\8dযবহার à¦\95রতà§\87 à¦\9aান, à¦¤à¦¬à§\87 à¦\86পনার [[Special:Preferences|পà¦\9bনà§\8dদ]] à¦\85পশনà§\87 à¦\8fà¦\95à¦\9fি à¦¬à§\88ধ à¦\87মà§\87à¦\87ল à¦ à¦¿à¦\95ানা à¦¨à¦¿à¦¬à¦¨à§\8dধিত à¦¥à¦¾à¦\95তà§\87 à¦¹à¦¬à§\87 à¦\8fবà¦\82 à¦\86পনার à¦¸à§\87à¦\9fি à¦¬à§\8dযবহারà§\87 à¦\95à§\8bন à¦¬à¦¾à¦§à¦¾ à¦¥à¦¾à¦\95তà§\87 à¦ªà¦¾à¦°à¦¬à§\87 à¦¨à¦¾à¥¤\n\nà¦\86পনার à¦¬à¦°à§\8dতমান à¦\86à¦\87পি à¦ à¦¿à¦\95ানা à¦¹à¦\9aà§\8dà¦\9bà§\87 $3, à¦\8fবà¦\82 à¦¬à¦¾à¦§à¦¾ à¦¦à¦¾à¦¨à§\87র à¦\86à¦\87ডি à¦¹à¦² #$5।\nযেকোন প্রশ্ন করার সময় উপরের সকল তথ্য উল্লেখ করুন।",
        "blockednoreason": "কোন কারণ দেওয়া হয়নি",
        "whitelistedittext": "পাতায় সম্পাদনা করতে আবশ্যই $1 করতে হবে।",
        "confirmedittext": "কোন সম্পাদনা করার আগে আপনার ই-মেইল ঠিকানাটি অবশ্যই নিশ্চিত করতে হবে। দয়া করে আপনার ই-মেইল ঠিকানাটি [[Special:Preferences|ব্যবহারকারীর পছন্দতালিকায়]] ঠিকমত দিন।",
        "yourdiff": "পার্থক্য",
        "copyrightwarning": "অনুগ্রহ করে লক্ষ্য করুন {{SITENAME}}-তে সমস্ত অবদান $2-এর আওতায় প্রাপ্য (বিস্তারিত $1-তে দেখুন)। আপনার জমা দেয়া লেখা যে কেউ হৃদয়হীনভাবে সম্পাদনা করতে এবং যথেচ্ছভাবে পুনর্বিতরণ করতে পারেন। আপনি যদি এ ব্যাপারে একমত না হন, তাহলে এখানে আপনার লেখা জমা দেবেন না।<br />\nআপনি আরো প্রতিজ্ঞা করছেন যে, এই লেখাগুলো আপনি নিজে লিখেছেন, বা সাধারণের ব্যবহারের জন্য উন্মুক্ত কোন উৎস থেকে সংগ্রহ করেছেন।\n'''স্বত্ব সংরক্ষিত কোন লেখা স্বত্বাধিকারীর অনুমতি ছাড়া এখানে জমা দেবেন না!'''",
        "copyrightwarning2": "অনুগ্রহ করে লক্ষ করুন: {{SITENAME}}-এর এই ভুক্তিতে আপনার লেখা বা অবদান অন্যান্য ব্যবহারকারীরা পরিবর্তন বা পরিবর্ধন করতে, এমনকি মুছে ফেলতে পারবেন। {{SITENAME}} এ আপনার সকল লেখালেখি/অবদান গনু ফ্রি ডকুমেন্টেশনের ($1) আওতায় বিনামূল্যে প্রাপ্য ও হস্তান্তরযোগ্য। আপনার জমা দেয়া লেখা যে কেউ হৃদয়হীনভাবে সম্পাদনা করতে এবং যথেচ্ছভাবে ব্যবহার করতে পারেন। আপনি যদি এ ব্যাপারে একমত না হন, তাহলে এখানে আপনার লেখা জমা দেবেন না। আপনি আরো প্রতিজ্ঞা করছেন যে, এই লেখাগুলো আপনি নিজে লিখেছেন (তবে কোন মৌলিক গবেষণা নয়) বা সাধারণের ব্যবহারের জন্য উন্মুক্ত কোন উৎস থেকে সংগ্রহ করেছেন। '''স্বত্ব সংরক্ষিত কোন লেখা স্বত্বাধিকারীর অনুমতি ছাড়া এখানে জমা দেবেন না।'''",
-       "editpage-cannot-use-custom-model": "à¦\8fà¦\87 à¦ªà¦¾à¦¤à¦¾à¦° à¦¬à¦¿à¦·à¦¯à¦¼à¦¬à¦¸à§\8dতà§\81র à¦®à¦¡à§\87ল পরিবর্তন করা যাবে না।",
+       "editpage-cannot-use-custom-model": "à¦\8fà¦\87 à¦ªà¦¾à¦¤à¦¾à¦° à¦¬à¦¿à¦·à¦¯à¦¼à¦¬à¦¸à§\8dতà§\81র à¦°à§\82প পরিবর্তন করা যাবে না।",
        "longpageerror": "'''ত্রুটি:  আপনার জমা দেয়া টেক্সটের পরিমাণ {{PLURAL:$1|এক কিলোবাইট|$1 কিলোবাইট}}, যা সর্বোচ্চ সীমা {{PLURAL:$2|এক কিলোবাইটের|$2 কিলোবাইটের}} চেয়ে বেশি।'''\nএটি সংরক্ষণ করা সম্ভব নয়।",
        "readonlywarning": "<strong>সতর্কীকরণ: রক্ষণাবেক্ষণের জন্য ডাটাবেজ অবরুদ্ধ রাখা হয়েছে, তাই এই মুহূর্তে আপনি আপনার সম্পাদনা সংরক্ষণ করতে পারবেন না।</strong>\nআপনি চাইলে লেখাটি অনুলিপি করে ও কোন টেক্সট ফাইলে প্রতিলেপন করার দ্বারা ভবিষ্যতের জন্য সংরক্ষণ করতে পারেন।\n\nসিস্টেম প্রশাসক যিনি এটি বন্ধ করেছেন তিনি এই ব্যাখ্যা দিয়েছেন: $1",
        "protectedpagewarning": "'''সতর্কীকরণ: এই পাতাটি বন্ধ করা হয়েছে; কেবলমাত্র প্রশাসক মর্যাদার ব্যবহারকারীরাই এটি সম্পাদনা করতে পারবেন।'''\nআপনার সুবিধার্থে পাতাটির সাম্প্রতিক সংরক্ষণ লগের বিবরণ নিচে দেওয়া হলো।",
        "userrights-lookup-user": "একজন ব্যবহারকারী নির্বাচন করুন",
        "userrights-user-editname": "ব্যবহারকারীর নাম লিখুন:",
        "editusergroup": "ব্যবহারকারী দল লোড করুন",
-       "editinguser": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|ব্যবহারকারীর}} জন্য ব্যবহারকারী অধিকার পরিবর্তন করছেন",
+       "editinguser": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|ব্যবহারকারীর}} ব্যবহারকারী অধিকার পরিবর্তন করছেন",
+       "viewinguserrights": "<strong>[[User:$1|$1]]</strong> $2 {{GENDER:$1|ব্যবহারকারীর}} ব্যবহারকারী অধিকার দেখছেন",
        "userrights-editusergroup": "ব্যবহারকারীর দল সম্পাদনা করো",
+       "userrights-viewusergroup": "ব্যবহারকারী দল দেখা",
        "saveusergroups": "{{GENDER:$1|ব্যবহারকারীর}} দল সংরক্ষণ করো",
        "userrights-groupsmember": "সদস্য:",
        "userrights-groupsmember-auto": "শর্তহীন সদস্য",
        "right-changetags": "নির্দিষ্ট সংস্করণ এবং দীর্ঘ সম্পাদনাগুলোতে [[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-editprotected": "সংরক্ষিত পাতা সম্পাদনা করুন",
        "grant-highvolume": "উচ্চ-মাত্রার সম্পাদনা",
        "grant-oversight": "ব্যবহারকারী লুকান ও ইতিহাস অপসারণ",
+       "grant-patrol": "পাতার পরিবর্তনে টহল দেয়া",
        "grant-privateinfo": "ব্যক্তিগত তথ্যে প্রবেশাধিকার",
        "grant-protect": "পাতাসমূহ সুরক্ষা ও অরক্ষিত করুন",
+       "grant-rollback": "পাতার পরিবর্তন ফেরত নেয়া",
        "grant-sendemail": "অন্য ব্যবহারকারীকে ইমেইল পাঠান",
        "grant-uploadeditmovefile": "ফাইল আপলোড, প্রতিস্থাপন এবং স্থানান্তর",
        "grant-uploadfile": "নতুন ফাইল আপলোড করুন",
        "action-writeapi": "রাইট এপিআই ব্যবহার করুন",
        "action-delete": "পাতাটি মুছে ফেলো",
        "action-deleterevision": "সংশোধনটি মুছে ফেলার",
+       "action-deletelogentry": "লগের ভুক্তি অপসারণ করার",
        "action-deletedhistory": "পাতার অপসারিত ইতিহাস দেখার",
+       "action-deletedtext": "অপসারিত সংশোধনের লেখা দেখার",
        "action-browsearchive": "অপসারিত পাতায় অনুসন্ধান করুন",
        "action-undelete": "পাতাটি পুনরুদ্ধার করার",
        "action-suppressrevision": "লুকানো সংস্করণগুলো পর্যালোচনা এবং পুনঃস্থাপন করার",
        "action-userrights-interwiki": "অন্যান্য উইকির ব্যবহারকারীদের অধিকারসমূহ সম্পাদনা করুন",
        "action-siteadmin": "ডাটাবেজ বন্ধ অথবা খুলুন",
        "action-sendemail": "ই-মেইল পাঠাও",
+       "action-editmyoptions": "নিজের পছন্দসমূহ সম্পাদনা করার",
        "action-editmywatchlist": "আপনার নজরতালিকা পরিবর্তন করুন",
        "action-viewmywatchlist": "আপনার নজরতালিকা দেখুন",
        "action-viewmyprivateinfo": "আপনার ব্যক্তিগত তথ্য দেখুন",
        "logempty": "মিলে যায় এমন কিছু লগে পাওয়া যায়নি।",
        "log-title-wildcard": "এই টেক্সট দিয়ে শুরু হওয়া শিরোনামগুলি অনুসন্ধান করা হোক",
        "showhideselectedlogentries": "নির্বাচিত লগগুলো দেখাও/লুকাও",
+       "log-edit-tags": "নির্বাচিত লগের ভুক্তির ট্যাগ সম্পাদনা করুন",
        "checkbox-select": "নির্বাচন: $1",
        "checkbox-all": "সব",
        "checkbox-none": "কোনটিই নয়",
        "activeusers-count": "গত {{PLURAL:$3|কালে|$3 দিনে}} সর্বমোট {{PLURAL:$1|কর্মের}} সংখ্যা $1টি",
        "activeusers-from": "ব্যবহারকারী দেখাও যাদের নাম এই অক্ষর দিয়ে শুরু:",
        "activeusers-groups": "এই দলভুক্ত ব্যবহারকারী দেখান:",
+       "activeusers-excludegroups": "এই দলভুক্ত ব্যবহারকারী বাদ দিন:",
        "activeusers-noresult": "কোনো ব্যবহারকারী পাওয়া যায়নি।",
        "activeusers-submit": "সক্রিয় ব্যবহারকারী প্রদর্শন করুন",
        "listgrouprights": "দলগত ব্যবহারকারী অধিকার",
        "listgrouprights-removegroup-self-all": "নিজের অ্যাকাউন্ট থেকে সকল দল অপসারণ",
        "listgrouprights-namespaceprotection-header": "নামস্থান নিষেধাজ্ঞাসমূহ",
        "listgrouprights-namespaceprotection-namespace": "নামস্থান",
+       "listgrouprights-namespaceprotection-restrictedto": "অধিকার যা ব্যবহারকারীকে সম্পাদনা করার অনুমতি দেয়",
        "listgrants": "কার্যভার",
        "listgrants-summary": "নিম্নে ব্যবহারকারী অধিকারের সাথে যুক্ত প্রবেশাধিকারসহ তাদের কার্যভারের একটি তালিকা দেয়া হয়েছে। ব্যবহারকারীরা তাদের অ্যাকাউন্ট ব্যবহার করতে অ্যাপ্লিকেশনকে অনুমোদন দিতে পারে, কিন্তু কার্যভারের উপর ভিত্তি করে সীমিত অনুমতি ব্যবহারকারীরা অ্যাপ্লিকেশনকে দিতে পারবেন। মূলত, একটি অ্যাপ্লিকেশন একজন ব্যবহারকারীর দেয়া অধিকারের অতিরিক্ত অধিকার ব্যবহার করতে পারবে না। পৃথক অধিকার সম্পর্কে [[{{MediaWiki:Listgrouprights-helppage}}|অতিরিক্ত তথ্য]] দেখুন।",
        "listgrants-grant": "কার্যভার",
        "emailccsubject": "আপনার বার্তার অনুলিপি $1-কে: $2",
        "emailsent": "ই-মেইল প্রেরণ করা হয়েছে",
        "emailsenttext": "আপনার ই-মেইল বার্তা প্রেরণ করা হয়েছে।",
-       "emailuserfooter": "এই ইমেইলটি {{SITENAME}} সাইটের \"{{int:emailuser}}\" সুবিধা ব্যবহার করে $1-এর পক্ষ থেকে {{GENDER:$2|$2}}-এর নিকট {{GENDER:$1|পাঠানো হয়েছে}}।",
+       "emailuserfooter": "এই ইমেইলটি {{SITENAME}} সাইটের \"{{int:emailuser}}\" সুবিধা ব্যবহার করে $1-এর পক্ষ থেকে {{GENDER:$2|$2}}-এর নিকট {{GENDER:$1|পাঠানো হয়েছে}}। {{GENDER:$2|আপনার}} উত্তরের ইমেইলটি সরাসরি {{GENDER:$1|মূল প্রেরকের}} কাছে পাঠানো হবে, সেই সাথে {{GENDER:$2|আপনার}} ইমেল ঠিকানা {{GENDER:$1|তাঁর}} কাছে প্রকাশ করা হবে।",
        "usermessage-summary": "বাদবাকি সিস্টেম বার্তা",
        "usermessage-editor": "সিস্টেম ম্যাসেঞ্জার",
        "usermessage-template": "MediaWiki:ব্যবহারকারী বার্তা",
        "rollback-success-notify": "$1-এর সম্পাদনাগুলি বাতিল করা হয়েছে; \n$2-এর করা শেষ সংস্করণে ফেরত নেওয়া হয়েছে। [$3 পরিবর্তন দেখুন]",
        "sessionfailure-title": "সেশন পরিত্যক্ত",
        "sessionfailure": "আপনার প্রবেশ সেশনে একটি সমস্যা হয়েছে বলে মনে হচ্ছে;\nসেশন হাইজ্যাক প্রতিরোধের উপায় হিসেবে এই কাজটি বাতিল করা হয়েছে।\nঅনুগ্রহ ব্রাউজারের \"পিছনে\" বোতাম চাপুন এবং যে পাতা থেকে এসেছিলেন, তা পুনঃলোড করুন এবং আবার চেষ্টা করুন।",
-       "changecontentmodel": "à¦\8fà¦\95à¦\9fি à¦ªà¦¾à¦¤à¦¾à¦° à¦¬à¦¿à¦·à¦¯à¦¼à¦¬à¦¸à§\8dতà§\81র à¦®à¦¡à§\87ল পরিবর্তন",
-       "changecontentmodel-legend": "বিষয়বসà§\8dতà§\81র à¦®à¦¡à§\87ল পরিবর্তন করুন",
+       "changecontentmodel": "à¦\8fà¦\95à¦\9fি à¦ªà¦¾à¦¤à¦¾à¦° à¦¬à¦¿à¦·à¦¯à¦¼à¦¬à¦¸à§\8dতà§\81র à¦°à§\82প পরিবর্তন",
+       "changecontentmodel-legend": "বিষয়বসà§\8dতà§\81র à¦°à§\82প পরিবর্তন করুন",
        "changecontentmodel-title-label": "পাতার শিরোনাম",
        "changecontentmodel-model-label": "পাতার বিষয়বস্তুর প্রতিরূপ",
        "changecontentmodel-reason-label": "কারণ:",
        "changecontentmodel-submit": "পরিবর্তন করুন",
        "changecontentmodel-success-title": "বিষয়বস্তুর প্রতিরূপ পরিবর্তিত হয়েছিলো",
        "changecontentmodel-success-text": "[[:$1]]-এর বিষয়বস্তুর ধরণ পরিবর্তন হয়েছে।",
-       "changecontentmodel-emptymodels-title": "কোন বিষয়বস্তুর মডেল উপলব্ধ নয়",
-       "log-name-contentmodel": "বিষয়বস্তুর মডেল পরিবর্তন লগ",
-       "logentry-contentmodel-change": "$1 $3 পাতার বিষয়বস্তুর মডেল \"$4\" থেকে \"$5\"-এ {{GENDER:$2|পরিবর্তন করেছেন}}",
+       "changecontentmodel-nodirectediting": "$1 বিষয়বস্তুর রূপ সরাসরি সম্পাদনা করা সমর্থন করে না",
+       "changecontentmodel-emptymodels-title": "কোন বিষয়বস্তুর রূপ উপলব্ধ নয়",
+       "log-name-contentmodel": "বিষয়বস্তুর রূপ পরিবর্তন লগ",
+       "logentry-contentmodel-change": "$1 $3 পাতার বিষয়বস্তুর রূপ \"$4\" থেকে \"$5\"-এ {{GENDER:$2|পরিবর্তন করেছেন}}",
        "logentry-contentmodel-change-revertlink": "প্রত্যাবর্তন",
        "logentry-contentmodel-change-revert": "প্রত্যাবর্তন",
        "protectlogpage": "সুরক্ষা লগ",
        "pageinfo-length": "পাতার দৈর্ঘ্য (বাইটে)",
        "pageinfo-article-id": "পাতার আইডি",
        "pageinfo-language": "পাতার তথ্যের ভাষা",
-       "pageinfo-content-model": "পাতার বিষয়বস্তুর মডেল",
+       "pageinfo-language-change": "পরিবর্তন",
+       "pageinfo-content-model": "পাতার বিষয়বস্তুর রূপ",
        "pageinfo-content-model-change": "পরিবর্তন",
        "pageinfo-robot-policy": "রোবটের মাধ্যমে ইন্ডেক্স করা হচ্ছে",
        "pageinfo-robot-index": "অনুমোদিত",
        "tag-filter": "[[Special:Tags|ট্যাগ]] ছাকনী:",
        "tag-filter-submit": "ছাকনী",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|ট্যাগ}}]]: $2)",
+       "tag-mw-contentmodelchange": "বিষয়বস্তুর রূপ পরিবর্তন",
+       "tag-mw-contentmodelchange-description": "সম্পাদনা যা একটি পাতার [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel বিষয়বস্তুর রূপ পরিবর্তন] করে",
        "tags-title": "ট্যাগসমূহ",
        "tags-intro": "এই পাতায় সফটওয়্যারটি একটি সম্পাদনা চিহ্নিত করার জন্য যে সকল ট্যাগ ব্যবহার করে তার তালিকা ও বর্ণনা রয়েছে।",
        "tags-tag": "ট্যাগ নাম",
        "feedback-useragent": "ব্যবহারকারী এজেন্ট:",
        "searchsuggest-search": "{{SITENAME}} অনুসন্ধান",
        "searchsuggest-containing": "যা আছে...",
+       "api-error-autoblocked": "আপনার আইপি ঠিকানাকে স্বয়ংক্রিয়ভাবে বাধা দেয়া হয়েছে কারণ এটি একজন অবরুদ্ধ ব্যবহারকারী দ্বারা ব্যবহৃত হয়েছিল।",
        "api-error-badaccess-groups": "আপনার এই উইকিতে ফাইল আপলোডের অনুমতি নেই।",
        "api-error-badtoken": "অভ্যন্তরীণ ত্রুটি: খারাপ টোকেন।",
        "api-error-blocked": "আপনাকে সম্পাদনা করা থেকে বাধা দেয়া হয়েছে।",
        "sessionprovider-nocookies": "কুকি নিষ্ক্রিয় করা। নিশ্চিত করুন যে আপনার কুকি সক্রিয় আছে এবং আবার শুরু করুন।",
        "randomrootpage": "অজানা মূল পাতা",
        "log-action-filter-block": "বাধাদানের ধরন:",
+       "log-action-filter-contentmodel": "বিষয়বস্তুর রূপ পরিবর্তনের ধরন:",
        "log-action-filter-delete": "অপসারণের ধরন:",
        "log-action-filter-import": "আমদানির ধরন:",
        "log-action-filter-managetags": "ট্যাগ ব্যবস্থাপনা কার্যের ধরন:",
        "log-action-filter-block-reblock": "বাধাদান পরিবর্তন",
        "log-action-filter-block-unblock": "বাধা অপসারণ",
        "log-action-filter-contentmodel-change": "বিষয়বস্তুর মডেল পরিবর্তন",
+       "log-action-filter-contentmodel-new": "অ-মানক বিষয়বস্তুর রূপসহ পাতা তৈরি",
        "log-action-filter-delete-delete": "পাতা অপসারণ",
        "log-action-filter-delete-restore": "পাতা পুনঃরুদ্ধার",
        "log-action-filter-delete-event": "লগ অপসারণ",
        "authmanager-create-disabled": "অ্যাকাউন্ট সৃষ্টিকরণ নিষ্ক্রিয় করা হয়েছে।",
        "authmanager-create-from-login": "আপনার একাউন্ট তৈরি করতে, ক্ষেত্রগুলি পূরণ করুন।",
        "authmanager-authplugin-setpass-failed-title": "পাসওয়ার্ড পরিবর্তন ব্যর্থ হয়েছে",
+       "authmanager-authplugin-setpass-failed-message": "প্রমাণীকরণ প্লাগইন পাসওয়ার্ড পরিবর্তন করতে অস্বীকৃতি জানিয়েছে।",
+       "authmanager-authplugin-create-fail": "প্রমাণীকরণ প্লাগইন অ্যাকাউন্ট তৈরি করতে অস্বীকৃতি জানিয়েছে।",
        "authmanager-authplugin-setpass-bad-domain": "অবৈধ ডোমেইন।",
        "authmanager-autocreate-noperm": "স্বয়ংক্রিয় অ্যাকাউন্ট সৃষ্টি মঞ্জুরিপ্রাপ্ত নয়।",
        "authmanager-userdoesnotexist": "ব্যবহারকারী অ্যাকাউন্ট \"$1\" অনিবন্ধিত।",
        "authmanager-provider-password": "পাসওয়ার্ড-ভিত্তিক প্রমাণীকরণ।",
        "authmanager-provider-password-domain": "পাসওয়ার্ড ও ডোমেইন-ভিত্তিক প্রমাণীকরণ।",
        "authmanager-provider-temporarypassword": "অস্থায়ী পাসওয়ার্ড",
+       "authprovider-confirmlink-request-label": "অ্যাকাউন্ট যা সংযুক্ত হওয়া উচিত",
        "authprovider-confirmlink-success-line": "$1: সংযোগ করা সফল হয়েছে।",
+       "authprovider-confirmlink-failed": "অ্যাকাউন্ট সংযোগ করা সম্পূর্ণরূপে সফল হয়নি: $1",
+       "authprovider-confirmlink-ok-help": "সংযোগ করা ব্যর্থতাসূচক বার্তাগুলি প্রদর্শন করার পরেও চালিয়ে যান।",
        "authprovider-resetpass-skip-label": "উপেক্ষা করো",
        "authprovider-resetpass-skip-help": "পাসওয়ার্ড পুনঃস্থাপন করা উপেক্ষা করুন।",
+       "authform-nosession-login": "প্রমাণীকরণ সফল ছিল, কিন্তু আপনার ব্রাউজার \"স্মরণ\" রাখতে পারবে না যে আপনি প্রবেশ করেছেন।\n\n$1",
+       "authform-nosession-signup": "অ্যাকাউন্ট তৈরি করা হয়েছে, কিন্তু আপনার ব্রাউজার \"স্মরণ\" রাখতে পারবে না যে আপনি প্রবেশ করেছেন।\n\n$1",
        "authform-newtoken": "টোকেন অনুপস্থিত। $1",
        "authform-notoken": "টোকেন অনুপস্থিত",
        "authform-wrongtoken": "ভুল টোকেন",
        "specialpage-securitylevel-not-allowed-title": "অনুমতি নেই",
        "specialpage-securitylevel-not-allowed": "দুঃখিত, আপনি এই পাতা ব্যবহার করতে অনুমতিপ্রাপ্ত নন কারণ আপনার পরিচয় যাচাই করা যায়নি।",
        "authpage-cannot-login": "প্রবেশ শুরু করা সম্ভন নয়।",
+       "authpage-cannot-login-continue": "প্রবেশ অব্যাহত রাখা সম্ভব নয়। সম্ভবত আপনার সেশনের সময় শেষ হয়েছে।",
+       "authpage-cannot-create": "অ্যাকাউন্ট সৃষ্টি আরম্ভ করা সম্ভব নয়।",
+       "authpage-cannot-create-continue": "অ্যাকাউন্ট সৃষ্টি অব্যাহত রাখা সম্ভব নয়। সম্ভবত আপনার সেশনের সময় শেষ হয়েছে।",
+       "authpage-cannot-link": "অ্যাকাউন্ট সংযোগ করা আরম্ভ করা সম্ভব নয়।",
+       "authpage-cannot-link-continue": "অ্যাকাউন্ট সংযোগ করা অব্যাহত রাখা সম্ভব নয়। সম্ভবত আপনার সেশনের সময় শেষ হয়েছে।",
        "cannotauth-not-allowed-title": "অনুমতি অস্বীকৃত",
        "cannotauth-not-allowed": "আপনি এই পাতাটি ব্যবহার করতে অনুমতিপ্রাপ্ত নন।",
        "changecredentials": "পরিচয়পত্র পরিবর্তন করুন",
        "removecredentials-success": "আপনার পরিচয়পত্র সরানো হয়েছে।",
        "credentialsform-provider": "পরিচয়পত্রের ধরন:",
        "credentialsform-account": "অ্যাকাউন্টের নাম:",
+       "cannotlink-no-provider-title": "আর কোন সংযোগযোগ্য অ্যাকাউন্ট নেই",
+       "cannotlink-no-provider": "আর কোন সংযোগযোগ্য অ্যাকাউন্ট নেই।",
        "linkaccounts": "অ্যাকাউন্ট সংযোগ করুন",
        "linkaccounts-success-text": "অ্যাকাউন্টটি সংযোগ করা হয়েছে।",
        "linkaccounts-submit": "অ্যাকাউন্ট সংযুক্ত করুন",
        "usercssispublic": "অনুগ্রহ করে লক্ষ্য করুন: সিএসএসের উপপাতাগুলিতে গোপনীয় তথ্য থাকা উচিত নয় যেহেতু অন্যান্য ব্যবহারকারীও এগুলি দেখতে পান।",
        "restrictionsfield-badip": "আইপি ঠিকানা অথবা পরিসীমা অবৈধ: $1",
        "restrictionsfield-label": "অনুমোদিত আইপি পরিসীমা:",
-       "restrictionsfield-help": "লাইন প্রতি একটি আইপি ঠিকানা বা CIDR পরিসীমা। সবকিছু সক্রিয় করতে<br><code>0.0.0.0/0</code><br><code>::/0</code><br>ব্যবহার করুন"
+       "restrictionsfield-help": "লাইন প্রতি একটি আইপি ঠিকানা বা CIDR পরিসীমা। সবকিছু সক্রিয় করতে<br><code>0.0.0.0/0</code><br><code>::/0</code><br>ব্যবহার করুন",
+       "revid": "সংশোধন $1",
+       "pageid": "পাতার আইডি $1"
 }
index 08a7965..5f63b94 100644 (file)
@@ -44,7 +44,9 @@
        "tog-showhiddencats": "نشودادن دسته بندیهای قایم شده",
        "underline-always": "همیشه",
        "underline-never": "هرگز",
-       "underline-default": "پیش نمایش مرورگر",
+       "underline-default": "پۈسدإ آ دوڤارتإ نيأر پيش فرز",
+       "editfont-sansserif": "فونت سان سئریف",
+       "editfont-serif": "فونت سريف",
        "sunday": "یکشنبه",
        "monday": "دوشنبه",
        "tuesday": "سه‌شنبه",
        "oct": "ئوکتوبر",
        "nov": "نوڤامر",
        "dec": "دئسامر",
+       "january-date": "جانڤيأ $1",
+       "february-date": "فإڤريأ $1",
+       "march-date": "مارس  $1",
+       "april-date": "آڤريل $1",
+       "may-date": "مإی $1",
+       "june-date": "جۈأن $1",
+       "july-date": "جۈلای $1",
        "period-am": "دم سوڤ",
        "period-pm": "پسين",
        "pagecategories": "{{PLURAL:$1|دسته|دسته ها}}",
        "editthispage": "اصلاح ای صفحه",
        "delete": "حذف",
        "protect": "حفاظت وحمایت",
+       "protect_change": "آلإشت کونين",
        "newpage": "صفحه تازه",
        "talkpage": "بحث ای صفحه",
        "talkpagelinktext": "چأک چئنە",
        "userlogin-yourname-ph": "نوم کاریاريتونأ بزنين",
        "yourpassword": "رمز:",
        "userlogin-yourpassword": "رازينإ گوڤأرتن",
+       "userlogin-yourpassword-ph": "رازينإ گوڤأرتن نأ بزأ",
+       "createacct-yourpassword-ph": "رازينإ گوڤأرتن نأ بزأ",
+       "createacct-yourpasswordagain": "پشت راسدکاري رازينإ گوڤأرتن",
        "userlogin-remembermypassword": "مۈنإ مإن سامۈنإ ڤاڌار",
        "login": "اویدن به سیستم",
        "nav-login-createaccount": "اویدن به سیستم",
        "createaccount": "درست کردن حساب کاربری",
        "gotaccount": "آیا تقریبا یه حساب کاربری دارین? '''$1'''.",
        "gotaccountlink": "اویدن به",
+       "userlogin-resetpassword-link": "رازینإ گوڤأرتن تۈ ز ڤيرتۈن رأهڌإ",
        "userlogin-helplink2": "هومياري کردن سي ڤامإن أڤوڌن",
+       "createacct-submit": "هساڤ خوتۈنإ راسد کونين",
+       "createacct-benefit-body1": "{{PLURAL:$1|ڤيرایشد|ڤيرایشدا}}",
+       "createacct-benefit-body2": "{{PLURAL:$1|بألگأ|بألگإ آ}}",
        "loginsuccesstitle": "اویدن با بخت وتوفیق به سیستم",
        "loginsuccess": "''' ایسا اویدن به داخل سایت {{SITENAME}} بعنوان \"$1\".'''",
        "nosuchuser": "کاربری به ای نام وجود نداره \"$1\".\nحروف نام را چک کنین, یا [[Special:CreateAccount|درست کنین یه حساب کاربری تازه]].",
        "recreate-moveddeleted-warn": "'''هشدار: ایسا در حال درست کردن دوباره صفحه‌ای هدین که قبلاً حذف وابیده '''در نظر داشته بوین که ادامه اصلاح ای صفحه کار درستی هده یا نه. نمایه حذف مربوط به ای صفحه سی راحتی کار در ادامه اویده",
        "viewpagelogs": "نشودادن نمایه ها سی ای صفحه",
        "currentrev": "نسخه جاری",
+       "currentrev-asof": "آخرين ڤانيأري جۈر $1",
        "revisionasof": "اصلاح $1",
        "revision-info": "نوسقإ ڤانيأري ڤابيڌإ جۈر $1 ڤا $2",
        "previousrevision": "← اصلاح قبلی",
        "history-feed-item-nocomment": "$1 در $2",
        "rev-delundel": "آلشد هال و بال ديإن",
        "history-title": "دڤارتإ دیئن ڤيرگار $1",
+       "difference-title": "فرخ مإنجقا ڤانإیريا \"$1\"",
        "lineno": "سطر $1:",
        "compareselectedversions": "مقایسه نسخه‌های انتخاب‌ وابیده",
        "editundo": "لغو اصلاح آخر",
        "search-result-size": "$1 ({{PLURAL:$2|1 ڤاجه یل|$2 ڤاجه یل}})",
        "search-redirect": "(ڤاگردۈني ز $1)",
        "search-section": "(بهرجا $1)",
+       "search-suggest": "منزۈرت یو بي:$1",
        "searchall": "همه",
        "search-nonefound": "هیژ نتیجه یی وا پی جست تو یکی نئ.",
        "preferences": "اولویتها",
        "tooltip-pt-mycontris": "یأ نومگأ ز هومياري {{GENDER:|ايسا}}",
        "tooltip-pt-login": "توصیه ابوه که به سیستم داخل بوین اما اجباری نه.",
        "tooltip-pt-logout": "رهدن زه سیستم",
+       "tooltip-pt-createaccount": "ايسا پشت گرم ڤابيڌينإ کإ یأ هساڤ راسد کونين و بياین ڤامإن. ب هرهال اي کار إژباري نارإ.",
        "tooltip-ca-talk": "صحبت درباره صفحه محتوا",
        "tooltip-ca-edit": "ڤيرایشت اي بلگه",
        "tooltip-ca-addsection": "شورۈ کردن یه بهرجا دیه",
        "tooltip-ca-watch": "اضاف کردن ای صفحه به لیست پیگیریهاتو",
        "tooltip-ca-unwatch": "حذف ای صفحه زه لیست پی‌گیری‌های ایسا",
        "tooltip-search": "جستن {{SITENAME}}",
+       "tooltip-search-go": "رۉ مإن بألگإیي کإ یأ نوم راستکي داشدإ بۈ.",
        "tooltip-search-fulltext": "بألگأ آنأ سي چونو نإڤشدإیي پإی جۈري کو",
        "tooltip-p-logo": "بإنیرين بإ سرآسۈنأ",
        "tooltip-n-mainpage": "دیدن صفحه اصلی",
index c61e871..e446a64 100644 (file)
@@ -18,7 +18,7 @@
        "tog-hideminor": "Къайладаха жима нисдарш керла могӀам юкъара",
        "tog-hidepatrolled": "Къайладаха гӀаролладина нисдарш оц могӀама керла нисдаршкахь",
        "tog-newpageshidepatrolled": "Къайлаяха гӀароллайина агӀонаш оьцу могӀама керла агӀонашкахь",
-       "tog-hidecategorization": "Ð\9aÑ\8aайлаÑ\8fÑ\85а Ð°Ð³Ó\80онийн ÐºÐ°Ñ\82егоÑ\80еÑ\88",
+       "tog-hidecategorization": "Ð\90гÓ\80онаÑ\88на Ñ\82Ó\80е ÐºÐ°Ñ\82егоÑ\80еÑ\88 Ñ\82оÑ\85аÑ\80 ÐºÑ\8aайладаккÑ\85а",
        "tog-extendwatchlist": "Шорбина тӀехьажарна могӀам, ша беригге а, хийцамаш чубогӀуш, тӀехьаббина боцурш а",
        "tog-usenewrc": "Лелабе дика могӀам керла чу хийцамашна (оьшу JavaScript)",
        "tog-numberheadings": "Ша шех хlитто терахь корташна",
@@ -29,6 +29,7 @@
        "tog-watchdefault": "ТӀетоха ас нисйина агӀонаш тергаме могӀам чу",
        "tog-watchmoves": "ТӀетоха ас цӀерш хийцина агӀонаш тергаме могӀам чу",
        "tog-watchdeletion": "ТӀетоха ас дӀаяьхна агӀонаш тергаме могӀанан чу",
+       "tog-watchuploads": "Аса чуяьхна файлаш тергаме могӀам юкъатоха",
        "tog-watchrollback": "Аса нисдар юхудаькхина агӀо сан тергаме могӀанан тӀетуху",
        "tog-minordefault": "Къастам бе нисйиначарн хlумцадеш кегийра долушсанна",
        "tog-previewontop": "Чуяккха хьалххьажар тадаран кора хьалха",
        "tog-watchlisthidebots": "Къайладаха тергаме могӀам чура ботан нисдинарш",
        "tog-watchlisthideminor": "Къайладаха кегийра нисдарш тергаме могӀам чура",
        "tog-watchlisthideliu": "Къайладаха бовзийтина болу декъашхойн нисдарш тергаме могӀам чура",
+       "tog-watchlistreloadautomatically": "Литтарна хийцам хилча авто-карлабаккха тергаме могӀам (оьшу JavaScript)",
        "tog-watchlisthideanons": "Къайладаха къайлаха болу декъашхойн нисдарш тергаме могӀам чура",
        "tog-watchlisthidepatrolled": "Къайладаха хьаьжина долу нисдарш тергаме могӀам чура",
+       "tog-watchlisthidecategorization": "АгӀонашна тӀе категореш тохар къайладаккха",
        "tog-ccmeonemails": "Дlадахьийта суна исанна кехат, аса дохьуьйтуш долу кхечу декъашхошна.",
        "tog-diffonly": "Ма гайта агlон чулацам шина башхонца цхьатерра йолуш",
        "tog-showhiddencats": "Гайта къайлаха йолу категореш",
        "anoneditwarning": "'''Тергам бе''': Ахьа хьай цӀарца тадарш деш дац. Хьан IP-адрес дӀаяздина хира ду хӀокху агӀон истори чу.",
        "anonpreviewwarning": "''Системин чу цагӀахь хьан IP-адрес агӀона истори чу дӀаяз лур ду.''",
        "missingsummary": "'''Дагадаийтар.''' Ахьа хийцамаш лаьцна доца яздина дац. Кнопка «{{int:savearticle}}» юху тӀетаӀича хийцамах лаьцна хӀума доцуш Ӏалашбира бу.",
+       "selfredirect": "<strong>Тергам бе:</strong> Ахьа кхуллуш ю из-за цӀе йолу агӀонан тӀе дӀасхьажорг.\nХийла мега, ДӀасхьажорг кхолла я таян ахьа хаьржина нийса йоцу агӀо.\nАхьа «{{int:savearticle}}» кнопка юха а тӀетаӀа яхь агӀо кхуллура ю.",
        "missingcommenttext": "Дехар до дӀаязбе хайн хаам лахахь.",
        "missingcommentheader": "'''Дагадаийтар.''' Ахьа хӀокху къамелан дӀахьедар/корта билгал бина бац. Кнопка «{{int:savearticle}}» юху тӀетаӀича хийцамах лаьцна хӀума доцуш Ӏалашбира бу.",
        "summary-preview": "Цуьнах лаьцна хирду:",
        "prefs-personal": "Долахь болу хаамаш",
        "prefs-rc": "Керла нисдарш",
        "prefs-watchlist": "Тергаме могӀам",
+       "prefs-editwatchlist": "Тергаме могӀаман хийцам",
+       "prefs-editwatchlist-label": "Сан тергаме могӀаман чура дӀаяздаршна хийцам:",
+       "prefs-editwatchlist-edit": "Сан тергаме могӀамам чура цӀерш дӀаяхар а, хьажар а",
+       "prefs-editwatchlist-raw": "Тергаме могӀам йоза санна нисбан",
+       "prefs-editwatchlist-clear": "Тергаме могӀам цӀанбан",
        "prefs-watchlist-days": "Денойн дукхалла:",
        "prefs-watchlist-days-max": "Къезиг $1 {{PLURAL:$1|дена}}",
        "prefs-watchlist-edits": "Тергаме могӀам чохь гойтучу нисдарийн максимум дукхалла:",
        "autosumm-newblank": "Кхоьллина еса агӀо",
        "lag-warn-normal": "{{PLURAL:$1|$1 Секунд}} хьалха бина хийцамаш хӀокху могӀамехь гуш ца хилла мега.",
        "lag-warn-high": "Сервераш синхронизаци еш тӀехьайисарна, {{PLURAL:$1|$1 секунд}} хьалха бина хийцамаш хӀокху могӀамехь гуш ца хилла мега.",
-       "watchlistedit-normal-title": "ТеÑ\80гаме Ð¼Ð¾Ð³Ó\80анийн Ñ\85ийÑ\86амаÑ\88",
+       "watchlistedit-normal-title": "ТеÑ\80гаме Ð¼Ð¾Ð³Ó\80аман Ñ\85ийÑ\86ам",
        "watchlistedit-normal-legend": "Тергаме могӀам юкъар дӀаяккхар",
        "watchlistedit-normal-explain": "Лахахь гойту хьан тергаме могӀамехь йолу агӀонаш.\nДӀаяздарш дӀадаха билгалде уьш такха тӀетаӀе кнопка «{{int:Watchlistedit-normal-submit}}».\nКхин хьа йиш ю [[Special:EditWatchlist/raw|йозан кепар могӀом нисба ]].",
        "watchlistedit-normal-submit": "ДӀадаха дӀаяздарш",
        "removecredentials": "ДӀадаха декъашхойн дӀаяздарш",
        "removecredentials-submit": "ДӀадаха декъашхойн дӀаяздарш",
        "credentialsform-provider": "ДӀаяздарийн тайпа:",
-       "credentialsform-account": "Декъашхочун цӀе:"
+       "credentialsform-account": "Декъашхочун цӀе:",
+       "userjsispublic": "Тергам бе: JavaScript бухара агӀонаш чохь къайлаха хаамаш хийла ца беза, уьш массо декъашхойн тӀекхочуш йолу дера.",
+       "usercssispublic": "Тергам бе: CSS бухара агӀонаш чохь къайлаха хаамаш хийла ца беза, уьш массо декъашхойн тӀекхочуш йолу дера."
 }
index 18887a3..0d9d219 100644 (file)
        "loginerror": "ھەڵەی چوونەژوورەوە",
        "createacct-error": "ھەڵە لە دروستکردنی ھەژمار",
        "createaccounterror": "ناتوانیت هەژماری بەکارهێنەر دروست بکەیت: $1",
-       "nocookiesnew": "ھەژماری بەکارھێنەر دروست‌کرا، بەڵام بە سەرکەوتوویی نەچوویتەوە ژوورەوە.\n{{SITENAME}} بۆ چوونەوە ژوورەوەی بەکارھێنەر لە شەکرۆکە کەڵک وەردەگرێت.\nتۆ شەکرۆکەکەت لەکارخستووە.\nتکایە شەکرۆکەکە کارا بکە و پاشان بە ناوی بەکارھێنەر و تێپەڕوشە بچۆ ژوورەوە.",
+       "nocookiesnew": "ھەژماری بەکارھێنەری دروست کرا، بەڵام نەچوویتەوە ژوورەوە.\n{{SITENAME}} بۆ چوونەوە ژوورەوەی بەکارھێنەر کوکی بەکاردەھێنێت.\nتۆ کوکییەکەکەت لەکارخستووە.\nتکایە کوکییەکە کارا بکە، پاشان بە ناوی بەکارھێنەری و تێپەڕوشەکەت بچۆ ژوورەوە.",
        "nocookieslogin": "{{SITENAME}} بۆ چوونەژوورەوە لە کووکی‌یەکان کەڵک وەرئەگرێت.\nڕێگەت نەداوە بە کووکی‌یەکان.\nڕێگەیان پێ بدەو و دیسان تێبکۆشە.",
        "nocookiesfornew": "ھەژماری بەکارھێنەری دروست نەکرا، چون ناتوانین سەرچاوەکەی پشتڕاست بکەینەوە.\nدڵنیا بە کوکییەکانت چالاک کردووە، پەڕەکە بار بکەوە و دیسان ھەوڵ بدە.",
        "noname": "ناوی بەکارهێنەرییەکی گۆنجاوت دیاری نەکردووه.",
index a7187c2..9ff10bc 100644 (file)
        "blockedtitle": "Uživatel zablokován",
        "blockedtext": "<strong>Vaší IP adrese či uživatelskému jménu byla zablokována možnost editace.</strong>\n\nZablokování {{GENDER:$4|provedl|provedla}} $1.\nUdaným důvodem bylo <em>$2</em>.\n\n* Začátek blokování: $8\n* Zablokování vyprší: $6\n* Blokovaný uživatel: $7\n\nPokud chcete zablokování prodiskutovat, můžete kontaktovat {{GENDER:$4|uživatele|uživatelku}} $1 či jiného [[{{MediaWiki:Grouppage-sysop}}|správce]].\nUvědomte si, že nemůžete použít funkci „Poslat e-mail“, jestliže nemáte ve svém [[Special:Preferences|nastavení]] uvedenu platnou e-mailovou adresu nebo pokud vám byla tato možnost zakázána.\nVaše IP adresa je $3 a&nbsp;identifikační číslo bloku je #$5; tyto údaje uvádějte ve všech dotazech na správce.",
        "autoblockedtext": "Vaše IP adresa byla automaticky zablokována, protože ji používal jiný uživatel, kterého zablokoval $1.\nUdaný důvod blokování:\n\n:<em>$2</em>\n\n* Začátek blokování: $8\n* Konec blokování: $6\n* Původně blokovaný uživatel: $7\n\nZablokování můžete prodiskutovat se správcem $1 nebo některým z dalších [[{{MediaWiki:Grouppage-sysop}}|správců]].\n\nUvědomte si však, že funkci „Poslat e-mail tomuto uživateli“ nemůžete použít, pokud nemáte ve svém [[Special:Preferences|uživatelském nastavení]] zadaný platný e-mail a nebylo vám zablokováno jeho užívání.\n\nVaše současná IP adresa je $3, číslo vašeho zablokování je #$5.\nProsíme, uveďte tyto údaje při komunikaci se správci.",
+       "systemblockedtext": "Vaše IP adresa byla automaticky zablokována softwarem MediaWiki.\nUdaný důvod blokování:\n\n:<em>$2</em>\n\n* Začátek blokování: $8\n* Konec blokování: $6\n* Původně blokovaný uživatel: $7\n\nVaše současná IP adresa je $3.\nProsíme, uveďte tyto údaje při komunikaci se správci.",
        "blockednoreason": "důvod nebyl zadán",
        "whitelistedittext": "Pro editaci se musíte $1.",
        "confirmedittext": "Pro editaci stránek je vyžadováno potvrzení vaší e-mailové adresy.\nNa stránce [[Special:Preferences|nastavení]] zadejte a nechte potvrdit svou e-mailovou adresu.",
        "withoutinterwiki-summary": "Tyto stránky neobsahují žádný mezijazykový odkaz:",
        "withoutinterwiki-legend": "Prefix",
        "withoutinterwiki-submit": "Zobrazit",
-       "fewestrevisions": "Stránky s nejméně verzemi",
+       "fewestrevisions": "Stránky s nejméně editacemi",
        "nbytes": "$1 {{PLURAL:$1|bajt|bajty|bajtů}}",
        "ncategories": "$1 {{PLURAL:$1|kategorie|kategorie|kategorií}}",
        "ninterwikis": "$1 {{PLURAL:$1|mezijazykový odkaz|mezijazykové odkazy|mezijazykových odkazů}}",
        "rollback-success-notify": "Editace uživatele $1 byly vráceny;\nobnovena poslední verze od uživatele $2. [$3 Zobrazit změny]",
        "sessionfailure-title": "Chyba relace",
        "sessionfailure": "Zřejmě je nějaký problém s vaším přihlášením;\nvámi požadovaná činnost byla stornována jako prevence před neoprávněným přístupem.\nStiskněte tlačítko „zpět“, obnovte stránku, ze které jste přišli, a zkuste činnost znovu.",
-       "changecontentmodel": "Změna modelu obsahu stránky",
+       "changecontentmodel": "Změnit model obsahu stránky",
        "changecontentmodel-legend": "Změnit model obsahu",
        "changecontentmodel-title-label": "Název stránky",
        "changecontentmodel-model-label": "Nový model obsahu",
        "pageinfo-length": "Velikost stránky (v bajtech)",
        "pageinfo-article-id": "ID stránky",
        "pageinfo-language": "Jazyk obsahu stránky",
+       "pageinfo-language-change": "změnit",
        "pageinfo-content-model": "Model obsahu stránky",
        "pageinfo-content-model-change": "změnit",
        "pageinfo-robot-policy": "Indexování roboty",
        "restrictionsfield-badip": "Neplatná IP adresa nebo rozsah: $1",
        "restrictionsfield-label": "Povolené rozsahy IP adres:",
        "restrictionsfield-help": "Jedna IP adresa nebo CIDR rozsah na řádek. Všechno povolíte pomocí<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "revize $1",
        "pageid": "Stránka s ID $1"
 }
index 4ae7a73..464c4b1 100644 (file)
        "blockedtitle": "Benutzer ist gesperrt",
        "blockedtext": "'''Dein Benutzername oder deine IP-Adresse wurde gesperrt.'''\n\nDie Sperrung wurde vom Administrator $1 durchgeführt.\nAls Grund wurde ''$2'' angegeben.\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\nDu kannst die „E-Mail an diesen Benutzer“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\nDeine aktuelle IP-Adresse ist $3 und die Sperrkennung lautet $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.",
        "autoblockedtext": "Deine IP-Adresse wurde automatisch gesperrt, da sie von einem anderen Benutzer genutzt wurde, der von $1 gesperrt wurde.\nAls Grund wurde angegeben:\n\n:''$2''\n\n* Beginn der Sperre: $8\n* Ende der Sperre: $6\n* Sperre betrifft: $7\n\nDu kannst $1 oder einen der anderen [[{{MediaWiki:Grouppage-sysop}}|Administratoren]] kontaktieren, um über die Sperre zu diskutieren.\n\nDu kannst die „E-Mail an diesen Benutzer“-Funktion nicht nutzen, solange keine gültige E-Mail-Adresse in deinen [[Special:Preferences|Benutzerkonto-Einstellungen]] eingetragen ist oder diese Funktion für dich gesperrt wurde.\n\nDeine aktuelle IP-Adresse ist $3, und die Sperr-ID ist $5.\nBitte füge alle Informationen jeder Anfrage hinzu, die du stellst.",
+       "systemblockedtext": "Dein Benutzername oder deine IP-Adresse wurde von MediaWiki automatisch gesperrt.\nDer angegebene Grund ist:\n\n:<em>$2</em>\n\n* Beginn der Sperre: $8\n* Ablauf der Sperre: $6\n* Sperre betrifft: $7\n\nDeine aktuelle IP-Adresse ist $3.\nBitte gib alle oben stehenden Details in jeder Anfrage an.",
        "blockednoreason": "keine Begründung angegeben",
        "whitelistedittext": "Du musst dich $1, um Seiten bearbeiten zu können.",
        "confirmedittext": "Du musst deine E-Mail-Adresse erst bestätigen, bevor du Bearbeitungen durchführen kannst. Bitte ergänze und bestätige deine E-Mail in den [[Special:Preferences|Einstellungen]].",
        "pageinfo-length": "Seitenlänge (in Bytes)",
        "pageinfo-article-id": "Seitenkennnummer",
        "pageinfo-language": "Seiteninhaltssprache",
+       "pageinfo-language-change": "ändern",
        "pageinfo-content-model": "Seiteninhaltsmodell",
        "pageinfo-content-model-change": "ändern",
        "pageinfo-robot-policy": "Indizierung durch Suchmaschinen",
        "restrictionsfield-badip": "Ungültige IP-Adresse oder ungültiger IP-Adressbereich: $1",
        "restrictionsfield-label": "Erlaubte IP-Adressbereiche:",
        "restrictionsfield-help": "Eine IP-Adresse oder ein CIDR-Bereich pro Zeile. Um alles zu aktivieren, verwende<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "revid": "v$1",
+       "revid": "Version $1",
        "pageid": "Seitenkennung $1"
 }
index 3f574b2..e6abfd8 100644 (file)
@@ -31,8 +31,8 @@
        },
        "tog-underline": "Bınê gırey de xete bance:",
        "tog-hideminor": "Vurnayışanê şenıkan pela vurnayışanê peyênan de bınımne",
-       "tog-hidepatrolled": "Vurnayışanê qontrolkerdeyan pela vurnayışê peyêni de bınımne",
-       "tog-newpageshidepatrolled": "Pelanê qontrolkerdeyan lista pelanê neweyan de bınımne",
+       "tog-hidepatrolled": "Vurnayışanê qontrol kerdeyan perra vurnayışê peyêni de bınımne",
+       "tog-newpageshidepatrolled": "Pelanê qontrol kerdeyan lista peranê  neweyan de bınımne",
        "tog-hidecategorization": "Pera kategorizasyoni bınımne",
        "tog-extendwatchlist": "Lista seyrkerdışi hera bıke ke vurnayışi pêro basê, tenya tewr peyêni nê",
        "tog-usenewrc": "Vurnayışê ke pela vurnayışanê peyênan û lista seyrkerdışi derê inan grube ke.",
        "tog-fancysig": "İmza rê mameleyê wikimeqaley bıke (bê gıreyo otomatik)",
        "tog-uselivepreview": "Verqayto giyane bıgureyne",
        "tog-forceeditsummary": "Mı ke xulasa veng verdaye, hay a mı ser de",
-       "tog-watchlisthideown": "Vurnayışanê mı lista mına seyrkerdışi de bınımne",
-       "tog-watchlisthidebots": "Lista seyrkerdışi ra vurnayışanê boti bınımne",
-       "tog-watchlisthideminor": "Vurnayışanê qıckekan lista mına seyrkerdışi de bınımne",
-       "tog-watchlisthideliu": "Lista seyrkerdışi ra vurnayışanê karberanê cıkewteyan bınımne",
+       "tog-watchlisthideown": "Vurnayışanê mı lista mına seyr kerdışi de bınımne",
+       "tog-watchlisthidebots": "Lista seyr kerdışi ra vurnayışanê boti bınımne",
+       "tog-watchlisthideminor": "Vurnayışanê qıckekan lista mına seyr kerdışi de bınımne",
+       "tog-watchlisthideliu": "Lista seyr kerdışi ra vurnayışanê karberanê cı kewteyan bınımne",
        "tog-watchlistreloadautomatically": "Filtra vıriyayış dı listey seyri otomatikman anewe kı",
-       "tog-watchlisthideanons": "Lista seyrkerdışi ra vurnayışanê karberanê anoniman bınımne",
-       "tog-watchlisthidepatrolled": "Lista seyrkerdışi ra vurnayışanê qontrolkerdeyan bınımne",
+       "tog-watchlisthideanons": "Lista seyr kerdışi ra vurnayışanê karberanê anoniman bınımne",
+       "tog-watchlisthidepatrolled": "Lista seyr kerdışi ra vurnayışanê qontrol kerdeyan bınımne",
        "tog-watchlisthidecategorization": "Pera kategorizasyoni bınımne",
        "tog-ccmeonemails": "E-posteyanê ke ez karberanê binan rê rışenan, mı rê kopya inan bırışe",
-       "tog-diffonly": "Qıyasê versiyonan de tek ferqan bımocne, pela butıne nê",
+       "tog-diffonly": "Zerrekê muhtevay, qıyasê versiyonan de tek ferqan bımocne",
        "tog-showhiddencats": "Kategoriyanê nımneya bıasne",
        "tog-norollbackdiff": "Peyser ardışi ra dıme ferqi measne",
        "tog-useeditwarning": "Wexto ke mı yew pela nizami be vurnayışanê nêqeydbiyayeyan caverdê, hay be mı ser de",
        "tog-prefershttps": "Ronışten akerden de tım greyo itimadın bıkarne",
        "underline-always": "Tım",
        "underline-never": "Qet",
-       "underline-default": "Cild ya zi cıgeyrayoğo hesebiyaye",
+       "underline-default": "Cild ya zi cı geyrayoğo hesebiyaye",
        "editfont-style": "Cayê vurnayışi de terzê nuştışi:",
-       "editfont-default": "Cıgeyrayoğo hesabiyaye",
-       "editfont-monospace": "Terzê nusteyê sabıtcagırewtoği",
+       "editfont-default": "Cı geyrayoğo hesabiyaye",
+       "editfont-monospace": "Terzê nusteyê sabıt mesafi",
        "editfont-sansserif": "Fontê Sans-serifi",
        "editfont-serif": "Font (çêşıdê nuştey) Serif",
        "sunday": "Kırê",
        "fri": "Yen",
        "sat": "Şem",
        "january": "Çele",
-       "february": "Sıbate",
+       "february": "Sıbat",
        "march": "Adar",
-       "april": "Nisane",
-       "may_long": "Gulane",
+       "april": "Lisan",
+       "may_long": "Gulan",
        "june": "Heziran",
-       "july": "Temuze",
+       "july": "Temuz",
        "august": "Tebaxe",
        "september": "Keşkelun",
        "october": "Tışrino Verên",
        "november": "Tışrino Peyên",
-       "december": "Kanun",
+       "december": "Gağan",
        "january-gen": "Çele",
-       "february-gen": "Sıbate",
+       "february-gen": "Sıbat",
        "march-gen": "Adar",
-       "april-gen": "Nisane",
-       "may-gen": "Gulane",
+       "april-gen": "Lisan",
+       "may-gen": "Gulan",
        "june-gen": "Heziran",
-       "july-gen": "Temuze",
+       "july-gen": "Temuz",
        "august-gen": "Tebaxe",
        "september-gen": "Keşkelun",
        "october-gen": "Tışrino Verên",
        "november-gen": "Tışrino Peyên",
-       "december-gen": "Kanun",
+       "december-gen": "Gağan",
        "jan": "Çel",
        "feb": "Sbt",
        "mar": "Adr",
-       "apr": "Nsn",
+       "apr": "Lsn",
        "may": "Gln",
        "jun": "Hez",
        "jul": "Tmz",
        "sep": "Kşk",
        "oct": "Tşv",
        "nov": "Tşp",
-       "dec": "Kan",
+       "dec": "n",
        "january-date": "$1 Çele",
-       "february-date": "$1 Sıbate",
+       "february-date": "$1 Sıbat",
        "march-date": "$1 Adar",
-       "april-date": "$1 Nisane",
-       "may-date": "$1 Gulane",
+       "april-date": "$1 Lisan",
+       "may-date": "$1 Gulan",
        "june-date": "$1 Heziran",
        "july-date": "$1 Temuze",
        "august-date": "$1 Tebaxe",
        "september-date": "$1 Keşkelun",
        "october-date": "$1 Tışrino Verên",
        "november-date": "$1 Tışrino Peyên",
-       "december-date": "$1 Kanun",
-       "period-am": "AM",
-       "period-pm": "PM",
+       "december-date": "$1 Gağan",
+       "period-am": "VD",
+       "period-pm": "BD",
        "pagecategories": "{{PLURAL:$1|Kategori|Kategoriy}}",
-       "category_header": "Pelê ke kategoriya \"$1\" derê",
+       "category_header": "Perrê kategoriya \"$1\"'i",
        "subcategories": "Kategoriyê bınêni",
-       "category-media-header": "Dosyeyê ke kategoriya \"$1\" derê",
-       "category-empty": "''Ena kategoriye de hewna qet nuştey ya zi medya çıniyê.''",
-       "hidden-categories": "{{PLURAL:$1|Kategoriya nımıtiye|Kategoriyê nımıtey}}",
+       "category-media-header": "Dosye yê ke kategoriya \"$1\" dı",
+       "category-empty": "''Ena kategori dı hewna qet nuştey ya zi medya çıni yê.''",
+       "hidden-categories": "{{PLURAL:$1|Kategoriya nımıte|Kategoriyê nımıtey}}",
        "hidden-category-category": "Kategoriyê nımıtey",
        "category-subcat-count": "{{PLURAL:$2|Na kategoriye de tenya na bınkategoriye esta.|Na kategoriye de, $2 ra pêro piya, {{PLURAL:$1|bınkategoriye esta|$1 bınkategoriy estê}}.}}",
        "category-subcat-count-limited": "Na kategoriye de {{PLURAL:$1|na kategoriya bınêne esta|nê $1 kategoriyê bınêni estê}}.",
-       "category-article-count": "{{PLURAL:$2|Na kategoriye de teyna ena pele esta.|Ebe $2 ra pêro piya {{PLURAL:$1|ena pele na kategoriye dera|$1 enê peli na kategoriye derê}}.}}",
-       "category-article-count-limited": "{{PLURAL:$1|Pela cêrêne|$1 Pelê cêrêni}} na kategoriye derê.",
+       "category-article-count": "{{PLURAL:$2|Na kategori dı teyna ena wesiqe est a.| $2 wesiqe ra {{PLURAL:$1|ena kategori de yê|$1 wesiqey kategori de yê}}.}}",
+       "category-article-count-limited": "{{PLURAL:$1|Pera cêrên|$1 Per cêrêni}} na kategori de yé",
        "category-file-count": "{{PLURAL:$2|Na kategori tenya dosya ya cêri muhtewa kena.|Na kategori de $2 ra pêro piya {{PLURAL:$1|1 dosya est a|$1 dosyey est ê}}.}}",
-       "category-file-count-limited": "{{PLURAL:$1|Dosya cêrêne|$1 Dosyê cêrêni}} na kategoriye derê.",
+       "category-file-count-limited": "{{PLURAL:$1|Dosye|$1 Dosyey}} na kategori de yê.",
        "listingcontinuesabbrev": "dewam...",
-       "index-category": "Pelê endeksıni",
-       "noindex-category": "Bê indeksın perri",
-       "broken-file-category": "Peleye ke gıreyê dosyeyanê ğeletan muhtewa kenê",
+       "index-category": "Perrê rêzıni",
+       "noindex-category": "Perrê bêrêzıni",
+       "broken-file-category": "Perrê  ke gıreyê dosyeyanê ğeletan muhtewa kenê",
        "categoryviewer-pagedlinks": "($1) ($2)",
-       "about": "Heqa cı de",
-       "article": "Pela zerreki",
+       "about": "Heqa",
+       "article": "Wesiqe",
        "newwindow": "(Teqaya newi de abena)",
        "cancel": "Peyd kı",
        "moredotdotdot": "Vêşi...",
        "morenotlisted": "Na lista qay kemi ya.",
-       "mypage": "Pele",
-       "mytalk": "Mesac",
+       "mypage": "Per",
+       "mytalk": "Vaten",
        "anontalk": "Vaten",
        "navigation": "Pusula",
        "and": "&#32;u",
-       "qbfind": "Bıvêne",
+       "qbfind": "Bıvin",
        "qbbrowse": "Çım ra viyarne",
        "qbedit": "Bıvurne",
-       "qbpageoptions": "Ena pele",
-       "qbmyoptions": "Pelê mı",
+       "qbpageoptions": "Na perrer",
+       "qbmyoptions": "Perrê mı",
        "faq": "PVP",
-       "faqpage": "Project: PZP",
+       "faqpage": "Project: PVP",
        "actions": "Hereketi",
        "namespaces": "Heruna nameyan",
        "variants": "Varyanti",
        "errorpagetitle": "Xeta",
        "returnto": "Peyser şo $1.",
        "tagline": "{{SITENAME}} ra",
-       "help": "Pti",
+       "help": "Pasti",
        "search": "Cı geyre",
        "searchbutton": "Cı geyre",
-       "go": "Şo",
-       "searcharticle": "Şo",
-       "history": "Tarixê pele",
-       "history_short": "Tarix",
-       "updatedmarker": "cıkewtena mına peyêne ra dıme biyo rocane",
-       "printableversion": "Asayışê çapkerdışi",
-       "permalink": "Gıreyo bêpeyni",
-       "print": "Çap ke",
-       "view": "Bıvêne",
-       "view-foreign": "$1 de bıvêne",
+       "go": "Şori",
+       "searcharticle": "Şori",
+       "history": "Tarixê perrer",
+       "history_short": "Veror",
+       "updatedmarker": "cı kewtena mına peyêne ra dıme biyo rocane",
+       "printableversion": "Versiyono nuşterniyaye",
+       "permalink": "Gıreyo vınderde",
+       "print": "Bınustern",
+       "view": "Bıvin",
+       "view-foreign": "$1 de bıvin",
        "edit": "Bıvurne",
        "edit-local": "Şınasnayışê lokali bıvurne",
        "create": "Vıraze",
        "create-local": "Şınasnayışê lokali cı ke",
-       "editthispage": "Ena pele bıvurne",
-       "create-this-page": "Na pele bınuse",
-       "delete": "Bestere",
-       "deletethispage": "Ena pele bestere",
+       "editthispage": "Na perrer bıvurne",
+       "create-this-page": "Na perer bıvıraz",
+       "delete": "Bestern",
+       "deletethispage": "Na perrer bestern",
        "undeletethispage": "Na perer mebesterne",
        "undelete_short": "{{PLURAL:$1|Yew vurnayışi|$1 Vurnayışan}} mestere",
        "viewdeleted_short": "{{PLURAL:$1|Yew vurnayışo esterıte|$1 Vurnayışanê esterıtan}} bımocne",
-       "protect": "Bışevekne",
+       "protect": "Bıstarnê",
        "protect_change": "bıvurne",
-       "protectthispage": "Ena pele bıpawe",
-       "unprotect": "Starkerdışi bıvurne",
-       "unprotectthispage": "Starkerdışe ena peler bıvurne",
-       "newpage": "Pela newiye",
-       "talkpage": "Ena pele sero werêne",
+       "protectthispage": "Ena perer bıpawe",
+       "unprotect": "Starnayışi bıvurne",
+       "unprotectthispage": "Starnayışê ena perer bıvurne",
+       "newpage": "Perra newi",
+       "talkpage": "Na per dı vatan kew",
        "talkpagelinktext": "Mesac",
-       "specialpage": "Pelê hısusiy",
+       "specialpage": "Perra xısusi",
        "personaltools": "Hacetê şexsiy",
        "articlepage": "Pera zerreki bıvin",
        "talk": "Vaten",
        "views": "Asayışi",
        "toolbox": "Haceti",
        "tool-link-userrights": "Grubanê {{GENDER:$1|karberi}} bıvırnë",
-       "tool-link-emailuser": "E-posta ya në{{GENDER:$1|karberi}}",
-       "userpage": "Pela karberi bıvêne",
-       "projectpage": "Pela proceyi bıvêne",
+       "tool-link-userrights-readonly": "Grubanê {{GENDER:$1|karberi}} bıvin",
+       "tool-link-emailuser": "E-posta ya në {{GENDER:$1|karberi}}",
+       "userpage": "Perra karberi bıvin",
+       "projectpage": "Perra proji bıvin",
        "imagepage": "Pera dosya bıasne",
        "mediawikipage": "Pera mesaci bıasne",
        "templatepage": "Pera şabloni bıasne",
        "viewhelppage": "Pera peşti bıvin",
        "categorypage": "Pela kategoriya bıasne",
-       "viewtalkpage": "Werênayışi bıvêne",
+       "viewtalkpage": "Vaten bıvin",
        "otherlanguages": "Zıwananê binan dı",
        "redirectedfrom": "($1 ra kırışı yê)",
-       "redirectpagesub": "Pela berdışi",
-       "redirectto": "Beno hetê:",
-       "lastmodifiedat": "Tewr peyên ena pele $1 dı $2 dı vuriyaya.",
+       "redirectpagesub": "Perra kırıştışi",
+       "redirectto": "Kırışêno:",
+       "lastmodifiedat": "{| style=\"border:1px solid skyblue; margin-bottom: 1em\" cellspacing=\"0\" cellpadding=\"3\" width=\"100%\"\n| style=\"font: 100% verdana; color:black\" align=\"center\" bgcolor=\"white\" |\n\nEna per tewr peyên $1 dı sehat $2 dı vuriya ya.\n|}",
        "viewcount": "Ena pele {{PLURAL:$1|rae|$1 rey}} vêniya.",
-       "protectedpage": "Pela pawıtiye",
+       "protectedpage": "Perra pawıyayi",
        "jumpto": "Şo be:",
        "jumptonavigation": "Navigasyon",
        "jumptosearch": "cı geyre",
        "copyrightpage": "{{ns:project}}:Heqa telifi",
        "currentevents": "Hediseyê rocaney",
        "currentevents-url": "Project:Hediseyê rocaney",
-       "disclaimers": "Redê mesuliyeti",
-       "disclaimerpage": "Project:Redê mesulêtê pêroyi",
-       "edithelp": "Peştdariya vurnayışi",
-       "helppage-top-gethelp": "Pti",
-       "mainpage": "Pela Seri",
-       "mainpage-description": "Pela seri",
+       "disclaimers": "Reddé  Mesuliyeti",
+       "disclaimerpage": "Project:Redê mesulêtê pêro",
+       "edithelp": "Pastiyer vurnayış",
+       "helppage-top-gethelp": "Pasti",
+       "mainpage": "Perra Seri",
+       "mainpage-description": "Perra seri",
        "policy-url": "Project:Terzê hereketi",
-       "portal": "Portalê cemaeti",
-       "portal-url": "Project:Portalê cemaeti",
+       "portal": "Portalê cemati",
+       "portal-url": "Project:Portalê cemati",
        "privacy": "Politikay nımıtışi",
        "privacypage": "Project:Xısusiyetê nımıtışi",
        "badaccess": "Xeta mısadey",
        "editlink": "bıvurne",
        "viewsourcelink": "çımey bıvêne",
        "editsectionhint": "Leteyo ke bıvuriyo: $1",
-       "toc": "Tedeestey",
-       "showtoc": "bımocne",
+       "toc": "Zerreki",
+       "showtoc": "bıasnê",
        "hidetoc": "bınımne",
        "collapsible-collapse": "Teng kı",
        "collapsible-expand": "Hera ke",
        "confirmable-confirm": "{{GENDER:$1|Şıma}} pêbawerê?",
-       "confirmable-yes": "Eya",
+       "confirmable-yes": "E",
        "confirmable-no": "Nê",
        "thisisdeleted": "Bıvêne ya zi $1 peyser biya?",
        "viewdeleted": "$1 bıvin?",
        "red-link-title": "$1 (pele çıniya)",
        "sort-descending": "Rêzkerdışo kêmbiyaye",
        "sort-ascending": "Rêzkerdışo zêdiyaye",
-       "nstab-main": "Pele",
-       "nstab-user": "Pela karberi",
-       "nstab-media": "Pela medya",
-       "nstab-special": "Pela xısusiye",
-       "nstab-project": "Pela proceyi",
+       "nstab-main": "Perr",
+       "nstab-user": "Perra karberi",
+       "nstab-media": "Perra medya",
+       "nstab-special": "Perra xısusi",
+       "nstab-project": "Perra proji",
        "nstab-image": "Dosya",
        "nstab-mediawiki": "Mesac",
        "nstab-template": "Şablon",
-       "nstab-help": "Pela peşti",
+       "nstab-help": "Perra pasti",
        "nstab-category": "Kategori",
-       "mainpage-nstab": "Pela seri",
+       "mainpage-nstab": "Perra seri",
        "nosuchaction": "Fealiyeto wınasi çıniyo",
        "nosuchactiontext": "URL ra kar qebul nêbı.\nŞıma belka URL şaş nuşt, ya zi gıreyi şaş ra ameyi.\nKeyepelê {{SITENAME}} eşkeno xeta eşkera bıkero.",
        "nosuchspecialpage": "Pela hısusiya wınasiyên çıniya.",
        "databaseerror": "Ğetay ardoği",
        "databaseerror-text": "Tabanda malumati de ğırabiya persayışi bi\nNa nusteber  zew ğırabin asınena.",
        "databaseerror-textcl": "Zu ğetaya erdamalumati persayışi ameya meydan.",
-       "databaseerror-query": "Perskerdış:$1",
+       "databaseerror-query": "Pers kerdış:$1",
        "databaseerror-function": "Fonksiyon: $1",
        "databaseerror-error": "Xeta: $1",
        "laggedslavemode": "Diqet: Pel de newe vıraşteyi belka çini .",
        "readonly": "database kılit biyo",
-       "enterlockreason": "Kılitkerdışi rê tarixê abiyayışê kılit ra piya yew sebeb bınusê.",
+       "enterlockreason": "Kılit kerdışi rê tarixê abiyayışê kılit ra piya yew sebeb bınusê.",
        "readonlytext": "Qey pawıtış ri yew sebeb vace. Texmini yew tarix vace şıma key pawıtış wedarneni:  $1",
        "missing-article": "Banqa, pela be nameyê \"$1\" $2 ke gani bıbo, nêdiye.\n\nEna belki seba yew vurnayışo kıhan ya zi tarixê gıreyê yew pele esteriya.\n\nEke wına niyo, belki ''software'' de yew xeta esta.\nKerem kerên, naye be nameyê ''URL''yi yew [[Special:ListUsers/sysop|karber]]i ra vacên.",
        "missingarticle-rev": "(rewizyon#: $1)",
        "mypreferencesprotected": "Terciha timar kerdışire icazeta şıam çıniya.",
        "ns-specialprotected": "Pelê xısusiyi nênê vurnayış.",
        "titleprotected": "No sername terefê [[User:$1|$1]] ra, afernayene ra şevekiyayo.\nSebebê xo <em>$2</em> dero.",
-       "filereadonlyerror": "Dosyay vurnayışê \"$1\" nê abê no lakin depoy dosya da \"$2\" mod dê  salt wendi deyo.\n\nXızmetkarê  kılitkerdışi wa bewni ro enay wa çımra ravyarno: \"$3\".",
+       "filereadonlyerror": "Dosyay vurnayışê \"$1\" nê abêno lakin depoy dosya da \"$2\" mod dê  salt wendi de yo.\n\nXızmetkarê  kılit kerdışi wa bewniro enay wa çım ra ravyarn o: \"$3\".",
        "invalidtitle-knownnamespace": "Canemey \"$2\" u metnê \"$3\" xırabo",
        "invalidtitle-unknownnamespace": "Sernameye nêşınasiya yana amraiya canameyo  $1 u metno \"$2\" xırab",
        "exception-nologin": "Şıma cıkewtış nêvıraşto",
        "botpasswords-label-appid": "Nameyê boti:",
        "botpasswords-label-create": "Vıraze",
        "botpasswords-label-update": "Rocane ke",
-       "botpasswords-label-cancel": "Bıtexelne",
+       "botpasswords-label-cancel": "Peyd kı",
        "botpasswords-label-delete": "Bestere",
        "botpasswords-label-resetpassword": "Parola raçarne",
        "botpasswords-label-grants-column": "Dayen",
        "resetpass_forbidden": "parolayi nêvuryayi",
        "resetpass-no-info": "şıma gani hesab akere u hona bıeşke bırese cı",
        "resetpass-submit-loggedin": "Parola bıvurne",
-       "resetpass-submit-cancel": "Bıtexelne",
+       "resetpass-submit-cancel": "Peyd kı",
        "resetpass-wrong-oldpass": "parolayo parola maqbul niyo.\nşıma ya parolaye xo vurnayo ya zi parolayo muwaqqat waşto.",
        "resetpass-recycled": "Parolaya şımaya newiye wa paroloya şımaya verêne ra ferqıne bo.",
        "resetpass-temp-emailed": "E postaya rışyayê yubkoda şıma ronıştış akerdo.  Ronıştışi xo temammkerdışi rê yu parolaya newi lazım a",
        "summary": "Xulasa:",
        "subject": "Mewzu:",
        "minoredit": "No yew vurnayışo werdiyo",
-       "watchthis": "Bewnı ena pele",
+       "watchthis": "Bewni ena per",
        "savearticle": "Pele qeyd kı",
        "savechanges": "Vurnayışan qeyd kı",
        "publishpage": "Perer bıhesırne",
        "templatesused": "{{PLURAL:$1|Şablon|Şabloni}} ke ena perrer de karneyayê:",
        "templatesusedpreview": "{{PLURAL:$1|Sablon|Sabloni}}  ke na verqayt de xebetnayê:",
        "templatesusedsection": "{{PLURAL:$1|Template|Templateyan}}  ke na qısım de xebetniyenê:",
-       "template-protected": "(kılit biyo)",
-       "template-semiprotected": "(nêmê ena pele kılit biyo)",
+       "template-protected": "(staryaye)",
+       "template-semiprotected": "(nime staryayış)",
        "hiddencategories": "Ena per de {{PLURAL:$1|1 kategoriyo nımıte|$1 kategoriyê nımıtey}} muhtewa benê:",
        "edittools": "<div id=\"specialcharss\" class=\"toccolours specialchars\" style=\"margin-top:.5em; padding: .3em .5em; font-size: 100%; color:#aaa; text-align:left;\" title=\"{{int:bw-edittools-tooltip}}\">\n<p class=\"specialbasic\" id=\"Standard\">\n'''{{int:bw-edittools-lead-in}}''' \n<charinsert>Á á É é Í í Ó ó Ú ú Ý ý</charinsert> –\n<charinsert>À à È è Ì ì Ò ò Ù ù </charinsert> –\n<charinsert> â Ê ê Î î Ô ô Û û </charinsert> –\n<charinsert>Ä ä Ë ë Ï ï Ö ö Ü ü Ÿ ÿ</charinsert> –\n<charinsert>Æ æ Ø ø Œ œ ẞ ß </charinsert> –\n<charinsert>Å å Ů ů </charinsert> –\n<charinsert>àã Ẽ ẽ ɛ̃ Ĩ ĩ Ñ ñ Õ õ ɔ̃ Ũ ũ </charinsert> –\n<charinsert>Рð Þ þ </charinsert> –\n<charinsert>Ç ç Ģ ģ Ķ ķ Ļ ļ Ņ ņ Ŗ ŗ Ş ş Ţ ţ </charinsert> –\n<charinsert>Ć ć Ĺ ĺ Ń ń Ŕ ŕ Ś ś Ý ý Ź ź </charinsert> –\n<charinsert>Č č Ď ď Ľ ľ Ň ň Ř ř Š š Ť ť Ž ž </charinsert> –\n<charinsert>Ǎ ǎ Ě ě Ǐ ǐ Ǒ ǒ Ǔ ǔ </charinsert> –\n<charinsert>Ā ā Ē ē Ī ī Ō ō Ū ū </charinsert> –\n<charinsert>ǖ ǘ ǚ ǜ </charinsert> –\n<charinsert>Ĉ ĉ Ĝ ĝ Ĥ ĥ Ĵ ĵ Ŝ ŝ Ŵ ŵ Ŷ ŷ </charinsert> –\n<charinsert>Ă ă Ğ ğ Ŭ ŭ </charinsert> –\n<charinsert>Ċ ċ Ė ė Ġ ġ Għ għ İ ı Ż ż </charinsert> –\n<charinsert>Ą ą Ę ę Į į Ų ų </charinsert> –\n<charinsert>Ő ő Ű ű </charinsert> –\n<charinsert>Đ đ Ħ ħ Ł ł Ŀ ŀ </charinsert> –\n<charinsert>Ɖ ɖ Ɛ ɛ Ƒ ƒ Ɣ ɣ Ŋ ŋ Ɔ ɔ Ʋ ʋ </charinsert> -\n<charinsert>Ə ə </charinsert> –\n<charinsert>– — ’</charinsert> –\n<charinsert>~ | ° ¹ ² ³ ⅛ ¼ ⅓ ⅜ ½ ⅝ ¾ ⅔ ⅞ € $ ¥ £ † × ← → ↔ ↑ ± ≠ © ® ™ ‰ «+» ‹+› „+“ „+” ‚+‘ ¡ ¿ …</charinsert> –\n<charinsert>&amp;nbsp; &nbsp; [[Category:+]] #REDIRECT[[+]] {{msg-mw|+|notext=1}} &#33;!FUZZY!! ~~~~  &lt;nowiki>+</nowiki></charinsert>\n<charinsert>ڈ ڑ ٹ </charinsert>\n<charinsert>ټ څ ځ ډ ړ ږ ښ ڼ ؤ ي ې ۍ ئ </charinsert>\n<charinsert>{{{+}}} {{+}} {{subst:+}} <noinclude>+</noinclude></charinsert>\n<charinsert>&lt;!--&nbsp;+&nbsp;--> &lt;br&nbsp;/></charinsert>\n</p></div>",
        "edittools-upload": "-",
        "search-category": "(kategori $1)",
        "search-file-match": "(zerreyê dosya yewbini gêno)",
        "search-suggest": "To va: $1",
-       "search-rewritten": "Neticey $ ra asenê.  Herunda ney wa neticanë $2'i bıvin",
+       "search-rewritten": "Neticey $1 ra asenê. Herunda ney wa neticanë $2'i bıvin",
        "search-interwiki-caption": "Proceyê bıray",
        "search-interwiki-default": "$1 ra neticey:",
        "search-interwiki-more": "(véşi)",
        "prefs-help-recentchangescount": "Ney de vurnayışê peyêni, tarixê pelan u cıkewteni asenê.",
        "prefs-help-watchlist-token2": "Na pawıtış nımnayi kılta listada şımaya.\nOke kıliti zano şeno listeya tamaşann bıvino. Poğta coy ra kesiya me hesırne. \n[[Special:ResetTokens|Na kıliti reset kerdışi re tiyay bıploğne]].",
        "savedprefs": "Tecihê şıma qeyd biy.",
-       "savedrights": "Qandé {{GENDER:$1|$1}} heqê karberi qeyd  biye.",
+       "savedrights": "{{GENDER:$1|$1}}  gruba karberi qeyd  biya.",
        "timezonelegend": "Warey saete:",
        "localtime": "saeta mehelliye:",
        "timezoneuseserverdefault": "Zey karkerdışê Wiki ($1)",
        "prefs-help-prefershttps": "Na tercih, fına dekewten dı bena aktiv.",
        "prefswarning-warning": "Şıma tercihanê xo de vurnayışi kerdi ke ney hewna qeyd nêbiyê. \nEke şıma na pele ra bêtıknayışê \"$1\" ra veciyê, tercihê şıma newe nêbenê.",
        "userrights": "İdarey heqanê karberan",
-       "userrights-lookup-user": "Grubanê karberi/karbere idare bıke",
+       "userrights-lookup-user": "Jew karber bıweçin",
        "userrights-user-editname": "Yew nameyê karberi cı kewe:",
-       "editusergroup": "Grupanê {{GENDER:$1|karberi}} bıvurne",
+       "editusergroup": "Grupanê karberi bıvurne",
        "editinguser": "{{GENDER:$1|karber}} [[User:$1|$1]] heqanê $2'i vurne no",
        "userrights-editusergroup": "Grubanê karberi/karbere sero bıgureye (bıxebetiye)",
+       "userrights-viewusergroup": "Grubanê karberi bıvin",
        "saveusergroups": "Grubanê {{GENDER:$1|karberi}} qeyd bıke",
        "userrights-groupsmember": "Ezayê:",
        "userrights-groupsmember-auto": "Ezao daxıl/ezaa daxıle ê:",
        "grant-protect": "Şeveknayış u wedarıtışê şeveknayışê pelan",
        "grant-sendemail": "Karberanê binan rê e-posta bırışê",
        "grant-uploadeditmovefile": "Dosyaya bar ke, bıvurnê  yana berê",
-       "grant-uploadfile": "Dosyaya newi bar ke",
+       "grant-uploadfile": "Dosye bıselagnê",
        "grant-basic": "Heqê basiti",
        "grant-viewdeleted": "Besteryaya peran u dosyaya bıasne",
        "grant-viewmywatchlist": "Lista serykerdışê xo bıvêne",
        "action-upload_by_url": "na dosya yew URL ra bar ke",
        "action-writeapi": "ser nuşte API gure bike",
        "action-delete": "ena pele bestere",
-       "action-deleterevision": "nê çımraviyarnayışi bestere",
-       "action-deletedhistory": "tarixê ena pel ki estereyî biya, ey bivine",
+       "action-deleterevision": "revizyoni besternê",
+       "action-deletelogentry": "roceka dekerdan bestern",
+       "action-deletedhistory": "verora esteriya perrer bıvin",
        "action-browsearchive": "pelanê esterıteyan bıgeyre",
-       "action-undelete": "ena pele meestere",
-       "action-suppressrevision": "revizyone ki nimnaye biye reyna bivîne u restore bike",
+       "action-undelete": "ena perer mestern",
+       "action-suppressrevision": "revizyonê nımnayi bıvin u timar kı.",
        "action-suppressionlog": "enê qeydê xısusi bıvêne",
        "action-block": "enê karberi vurnayışi ra bıreyne",
        "action-protect": "seviyeyê pawitişî se ena pele bivurne",
        "action-userrights-interwiki": "heqqa karberanê ke wikiyê binî de hemî bivurne",
        "action-siteadmin": "database kilit bike ya zi a bike",
        "action-sendemail": "e-posta bırşe",
+       "action-editmyoptions": "Tercihanê xo bıvurne",
        "action-editmywatchlist": "Listeyseyran de xo bıvırne",
        "action-viewmywatchlist": "Listeyseyran de xo bıvin",
        "action-viewmyprivateinfo": "Xısusi tercihane xo bıvin",
        "recentchanges-page-added-to-category": "[[:$1]] kerd kategoriye miyan",
        "recentchanges-page-removed-from-category": "[[:$1]] kategoriye ra vet",
        "autochange-username": "MediaWiki vurnayışo otomatik",
-       "upload": "Dosya bar ke",
-       "uploadbtn": "Dosya bar ke",
+       "upload": "Dosye bıselagnê",
+       "uploadbtn": "Dosye bıselagnê",
        "reuploaddesc": "Barkerdışi iptal ke u peyser şo formê barkerdışi",
        "upload-tryagain": "Deskripyonê dosyayî ke vurîya ey qeyd bike",
        "uploadnologin": "Şıma cıkewtış nêvıraşto",
        "upload-too-many-redirects": "Eno URL de zaf redireksiyonî esto.",
        "upload-http-error": "Yew ğeletê HTTPî biyo: $1",
        "upload-copy-upload-invalid-domain": "Na domain ra kopyayê barkerdışanê nêbenê.",
-       "upload-dialog-title": "Dosya bar ke",
+       "upload-dialog-title": "Dosye bıselagnê",
        "upload-dialog-button-cancel": "Bıterkın",
        "upload-dialog-button-done": "Temam",
        "upload-dialog-button-save": "Bışevekne",
        "mimesearch": "MIME bigêre",
        "mimesearch-summary": "Na pele, dosyayanê MIME goreyê tewran ra parzûn kena. Cıkewtış: tewrê zerreki/tewro bınên ya zi tewrê zerreki/*, nımune: <code>image/jpeg</code>.",
        "mimetype": "Babetê NIME",
-       "download": "Bar ke",
+       "download": "Bıselagnê",
        "unwatchedpages": "Pelanê seyrnibiyeyî",
        "listredirects": "Listeya Hetenayışan",
        "listduplicatedfiles": "Lista dosyeyanê ke kopyaya cı vêniyena",
        "listusers-desc": "Kemeyen rézed ratn",
        "usereditcount": "$1 {{PLURAL:$1|vurnayîş|vurnayîşî}}",
        "usercreated": "$2 de $1 {{GENDER:$3|viraziya}}",
-       "newpages": "Pelê newey",
+       "newpages": "Perrê newey",
        "newpages-submit": "Bımocne",
        "newpages-username": "Nameyê karberi:",
        "ancientpages": "Tewr pelê kıhani",
        "removedwatchtext": "Ena pela \"[[:$1]]\" biya wedariya [[Special:Watchlist|listeyê seyr-kerdışi şıma]].",
        "removedwatchtext-short": "Pera $1`i listeya seyran de şıma ra wedari yê",
        "watch": "Seyr ke",
-       "watchthispage": "Bewnı ena pele",
+       "watchthispage": "Bewni ena per",
        "unwatch": "Teqib meke",
        "unwatchthispage": "temaşa kerdışê peli vındarn.",
        "notanarticle": "mebhesê peli niyo",
        "protect-locked-blocked": "seviyeya qedexe biyayeyan nevuriyeno.\n'''$1''' eyarê peli:",
        "protect-locked-dblock": "semedê kılidê database ya aktifi şıma neeşkeni seviyeya pawıtışi buvurni.\n'''$1''' eyarê no peli:",
        "protect-locked-access": "Karber hesabê şıma nêşeno  staryaye sewiyey ena peler bıvurno.\nHesıbyayê sazê pela da '''$1''' enêyê:",
-       "protect-cascadeon": "Ena pele nıka kılit biya, çıke na pele zerreyê lista {{PLURAL:$1|pela ke bınê şevekiyayışê qedemeyıni dera|pelê ke bınê şevekiyayışê qedemeyıni derê}}.\nTı şenê sewiyaya kılitkerdışi bıvurnê, feqat tı nêşenê şevekiyayışê qedemeyıni bıvurnê.",
+       "protect-cascadeon": "Ena pele nıka kılit biya, çıke na pele zerreyê lista {{PLURAL:$1|pela ke bınê staryayışi qedemeyıni dera|pelê ke bınê şevekiyayışê qedemeyıni derê}}.\nTı şenê sewiya ya kılit kerdışi bıvurnê, feqat tı nêşenê staryayışi qedemeyıni bıvurnê.",
        "protect-default": "Destur bıde karberan pêrune",
        "protect-fallback": "Tenya karberanê be izna \"$1\" rê destur bıde",
        "protect-level-autoconfirmed": "Karberanê neweyan u qeyd-nêbiyaoğan kılit ke",
        "undeletepagetext": "{{PLURAL:$1|pelo|$1 pelo}} cerın hewn a şiyo labele hema zi arşiv de yo u tepiya geriyeno.\nArşiv daimi pak beno.",
        "undelete-fieldset-title": "revizyonan tepiya bar ker",
        "undeleteextrahelp": "Qey ardışê pel u verê pelani tuşê '''tepiya biya!'''yi bıtıknê. qey ciya ciya ardışê verê pelani zi qutiye tesdiqi nişane kerê u tuşê '''tepiya biya!'''yi bıtıknê '''''{{int:undeletebtn}}'''''.. qey hewn a kerdışê qutiya tesdiqan u qey sıfır kerdışê cayê sebebani zi tuşê '''agêr caverd/aça ker'''i bıtıknê '''''{{int:undeletebtn}}'''''..",
-       "undeleterevisions": "$1 {{PLURAL:$1|revizyon|revizyon}} esteriya yë",
+       "undeleterevisions": "$1 {{PLURAL:$1|revizyon|revizyoni}} esteriya yë",
        "undeletehistory": "eke şıma pel tepiya biyari heme revizyonî zi tepiya yeni.\neke yew pel hewn a biyo u pê nameyê o peli newe ra yew pel bıvıraziyo, revizyonê o pelê verıni zerreyê no pel de aseno.",
        "undeleterevdel": "eke pelo serın de netice bıdo ya zi revizyoni qısmen hewn a bıbiy hewn a kerdışi tepiya nêgeriyeno.",
        "undeletehistorynoadmin": "na madde hewn a biya. sebebê hewna kerdışi u teferruatê karber ê ke maddeyi vıraştı cêr de diyayî. revizyonê hewn a biyayeyani têna serkari vineni",
        "tooltip-invert": "nameyo ke nışan biyo (u nameyo elekeyın zi nışanyyayo se) vurnayışan  zerrekan nımtışi re ena dore tesdiqi nışan kerê",
        "namespace_association": "Heruna namanê elaqedaran",
        "tooltip-namespace_association": "Herunda canemiya elekeyın nışan kerdışi sero qıse kerdışi yana zerre dekerdışi rê ena dora tesdiqi nışan kerê",
-       "blanknamespace": "(Ser)",
+       "blanknamespace": "(Wesiqe)",
        "contributions": "İştırakê {{GENDER:$1|karber}}i",
        "contributions-title": "Dekerdenê karber de $1",
        "mycontris": "İştıraki",
        "whatlinkshere": "Linkê tedeestey",
        "whatlinkshere-title": "Wesiqe da \"$1\" rê gıre dayen perri",
        "whatlinkshere-page": "Pele:",
-       "linkshere": "Ena peleyan grey biya '''[[:$1]]''':",
+       "linkshere": "Pera <strong>[[:$1]]</strong> rê gıre dayen perri",
        "nolinkshere": "Per da '''[[:$1]]''' rê pera ke gıre dana çıniya.",
        "nolinkshere-ns": "Ena cayê nameyî de yew pel zi '''[[:$1]]''' rê link nibeno.",
        "isredirect": "pera hetenayışi",
        "whatlinkshere-next": "{{PLURAL:$1|verni|verni $1}}",
        "whatlinkshere-links": "← gırey",
        "whatlinkshere-hideredirs": "Hetenayışê $1",
-       "whatlinkshere-hidetrans": "Açarnayışê $1",
+       "whatlinkshere-hidetrans": "Çarnayışan $1",
        "whatlinkshere-hidelinks": "Gıreyê $1",
        "whatlinkshere-hideimages": "Gıreyê dosya $1",
        "whatlinkshere-filters": "Parzûn",
        "ipb-blocklist-duration-left": "$1 vet",
        "unblockip": "Hesabê karberî a bike",
        "unblockiptext": "Cıreştışê nuştışê IP ya zi karberio ke ver ra gêriyayo, seba peyser barkerdışi dey rê formê cêrêni bıgurenên.",
-       "ipusubmit": "Enê kılitkerdışi wedare",
+       "ipusubmit": "Enê kılit kerdışi wedarnê",
        "unblocked": "[[User:$1|$1]] blok biyo",
        "unblocked-range": "Blokey $1'i wederya",
        "unblocked-id": "Blokê $1î wedariyayo",
        "createaccountblock": "Hesab viraştîş blok biyo",
        "emailblock": "e-mail blok biyo",
        "blocklist-nousertalk": "ti nieşken pele minaqaşe xo bivurne",
-       "ipblocklist-empty": "Lista kılitkerdışi venga.",
+       "ipblocklist-empty": "Listay kılit kerdışi venga.",
        "ipblocklist-no-results": "Adresa IPya waştiye ya zi nameyê karberi kılit nêbiyo.",
        "blocklink": "kılit ke",
        "unblocklink": "bloki wedare",
-       "change-blocklink": "kılitkerdışi bıvurne",
+       "change-blocklink": "kılit kerdışi bıvurne",
        "contribslink": "iştıraki",
        "emaillink": "e-poste bırışe",
        "autoblocker": "Şıma otomatikmen kılit biy, çıke adresa şımaya ''IP''y terefê \"[[User:$1|$1]]\" gureniyena.\nSebebê kılitbiyayışê $1'i \"$2\"o",
        "tooltip-n-currentevents": "Vurnayışanê peyênan de melumatê pey bıvêne",
        "tooltip-n-recentchanges": "Wiki de yew lista vurriyayışanê peyênan",
        "tooltip-n-randompage": "Pelê da raştameyiye bar ke",
-       "tooltip-n-help": "Cayê peştigırewtışi",
+       "tooltip-n-help": "Cayê pesti gırotış",
        "tooltip-t-whatlinkshere": "Lista pelanê wikiya pêroina ke tiya gırê bena",
        "tooltip-t-recentchangeslinked": "Vurnayışê peyênê pelanê ke ena pela ra gırê biyê",
        "tooltip-feed-rss": "RSS feed qe ena pele",
        "tooltip-t-emailuser": "Ena karber ri yew email bırış",
        "tooltip-t-upload": "Dosyeyan bar ke",
        "tooltip-t-specialpages": "Yew lista pelanê xasanê pêroyinan",
-       "tooltip-t-print": "Versiyonê peleyo ke şeno çap bıkeriyo.",
+       "tooltip-t-print": "Versiyono perre ro ke nuşterniyaye.",
        "tooltip-t-permalink": "Gırêyo daimi be ena versiyonê pele",
        "tooltip-ca-nstab-main": "Pela zerreki bıvêne",
        "tooltip-ca-nstab-user": "Pela karberi bıvêne",
        "anonymous": "{{PLURAL:$1|karberê|karberê}} anonimi yê keyepelê {{SITENAME}}i",
        "siteuser": "karberê {{SITENAME}}i $1",
        "anonuser": "karberê anonim o {{SITENAME}}i $1",
-       "lastmodifiedatby": "Ena per tewr peyên roca $2, $1 de terefê $3 ra vurmaya ya.",
+       "lastmodifiedatby": "Ena per tewr peyên roca $2, $1 de terefê $3 ra vurneya ya.",
        "othercontribs": "xebatê $1 ıney geriyayo diqqeti/geriyayo nezer.",
        "others": "bini",
        "siteusers": "{{SITENAME}} {{PLURAL:$2|karber|karberan}} $1",
        "pageinfo-redirects-value": "$1",
        "pageinfo-subpages-name": "Bınpelê na pela",
        "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|serçarnayış|serçarnayışi}}; $3 {{PLURAL:$3|nêserçarnayış|nêserçarnayışi}})",
-       "pageinfo-firstuser": "Pela vıraşter",
-       "pageinfo-firsttime": "Demê pela vıraştışi",
+       "pageinfo-firstuser": "Vıraştoğê perrer",
+       "pageinfo-firsttime": "Vıraştena tarixê perrer",
        "pageinfo-lastuser": "Vurnayoğo peyên",
        "pageinfo-lasttime": "Deme u vurnayışo peyên",
        "pageinfo-edits": "Amarina vurnayışan pêro",
        "pageinfo-hidden-categories": "{{PLURAL:$1|Kategoriya nımıtiye|Kategoriyê nımıtey}} ($1)",
        "pageinfo-templates": "{{PLURAL:$1|Şablono|Şablonê}} ke mocniyenê ($1)",
        "pageinfo-transclusions": "{{PLURAL:$1|1 Pele|$1 Pelan}} de bestiya pıra",
-       "pageinfo-toolboxlink": "Melumatê pele",
+       "pageinfo-toolboxlink": "Melumatê perrer",
        "pageinfo-redirectsto": "Beno hetê",
        "pageinfo-redirectsto-info": "melumat",
        "pageinfo-contentpage": "Zey jû pela zerreki hesebiyena",
        "feedback-bugcheck": "Harika! Sadece [xırabina ke $1 ] çınyayışê cı kontrol keno.",
        "feedback-bugnew": "Mı qontrol ke. Xetaya newi xeber ke",
        "feedback-bugornote": "Jew mersela teferruato teknik esta şıma reca malumatê şıma hazıro se [ $1  jew xırab rapor] bıvinê.Zewbi zi, formê cerê xo rê şenê karfiyê. Vatışê xo pela da \"[ $3  $2 ]\", namey karber dê xoya piya u wasteriya karfiye.",
-       "feedback-cancel": "Bıtexelne",
+       "feedback-cancel": "Peyd kı",
        "feedback-close": "Biya star",
        "feedback-error1": "Xeta: API ra neticey ne vıcyay",
        "feedback-error2": "Xeta: Timar kerdış nebı",
index 0774b0f..e1fdc42 100644 (file)
        "blockedtitle": "User is blocked",
        "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 \"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.",
        "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* Expiration 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.",
+       "systemblockedtext": "Your username or IP address has been automatically blocked by MediaWiki.\nThe reason given is:\n\n:<em>$2</em>\n\n* Start of block: $8\n* Expiration of block: $6\n* Intended blockee: $7\n\nYour current IP address is $3.\nPlease include all above details in any queries you make.",
        "blockednoreason": "no reason given",
        "whitelistedittext": "Please $1 to edit pages.",
        "confirmedittext": "You must confirm your email address before editing pages.\nPlease set and validate your email address through your [[Special:Preferences|user preferences]].",
        "wlshowhidemine": "my edits",
        "wlshowhidecategorization": "page categorization",
        "watchlist-options": "Watchlist options",
-       "watchlist-mark-all-visited": "Are you sure you want to reset unseen watchlist changes by marking all pages as visited?",
        "watching": "Watching...",
        "unwatching": "Unwatching...",
        "watcherrortext": "An error occurred while changing your watchlist settings for \"$1\".",
        "cant-move-to-user-page": "You do not have permission to move a page to a user page (except to a user subpage).",
        "cant-move-category-page": "You do not have permission to move category pages.",
        "cant-move-to-category-page": "You do not have permission to move a page to a category page.",
+       "cant-move-subpages": "You do not have permission to move subpages.",
+       "namespace-nosubpages": "Namespace \"$1\" does not allow subpages.",
+       "movepage-max-pages": "The source page has more than the maximum $1 {{PLURAL:$1|subpage|subpages}}.",
        "newtitle": "New title:",
        "move-watch": "Watch source page and target page",
        "movepagebtn": "Move page",
        "pageinfo-length": "Page length (in bytes)",
        "pageinfo-article-id": "Page ID",
        "pageinfo-language": "Page content language",
+       "pageinfo-language-change": "change",
        "pageinfo-content-model": "Page content model",
        "pageinfo-content-model-change": "change",
        "pageinfo-robot-policy": "Indexing by robots",
        "restrictionsfield-badip": "Invalid IP address or range: $1",
        "restrictionsfield-label": "Allowed IP ranges:",
        "restrictionsfield-help": "One IP address or CIDR range per line. To enable everything, use<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "revid": "r$1",
+       "revid": "revision $1",
        "pageid": "page ID $1"
 }
index 68d3155..2056f6d 100644 (file)
        "views": "Vidoj",
        "toolbox": "Iloj",
        "tool-link-userrights": "Ŝanĝi grupojn de ĉi tiu {{GENDER:$1|uzanto}}",
+       "tool-link-userrights-readonly": "Vidi grupojn de {{GENDER:$1|uzanto}}",
        "tool-link-emailuser": "Sendi retpoŝton al ĉi tiu {{GENDER:$1|uzanto}}",
        "userpage": "Vidi uzantopaĝon",
        "projectpage": "Rigardi projektopaĝon",
        "botpasswords-label-delete": "Forigi",
        "botpasswords-label-resetpassword": "Rekomencigi la pasvorton",
        "botpasswords-label-grants": "Uzeblaj permesdonoj:",
-       "botpasswords-help-grants": "Ĉiu permesdono provizas aliron al listitaj uzantaj permisoj, kiujn uzantkonto jam havas. Vidu la [[Special:ListGrants|tabelon de permesdonoj]] por pli da informo.",
+       "botpasswords-help-grants": "Rajtigiloj permesas aliron al rajtoj jam provizita al via uzantkonto. Ebligi rajtigilojn ĉi tie ne provizas aliron al ajnaj rajtoj ke via uzantkonto ne alie havus. Vidu la [[Special:MyLanguage/Special:ListGrants|tablo de gratifikoj]] por pli da informo.",
        "botpasswords-label-grants-column": "Permeso donita",
        "botpasswords-bad-appid": "La robota nomo \"$1\" estas malvalida.",
        "botpasswords-insert-failed": "Aldono de la robota nomo \"$1\" ne sukcesis. Ĉu ĝi jam estis aldonita?",
        "blockedtitle": "La uzanto estas forbarita.",
        "blockedtext": "'''Via konto aŭ IP-adreso estis forbarita'''\n\nLa forbaro estis farita de $1.\nLa skribita kialo estas ''$2''.\n\n* Komenco de forbaro: $8\n* Findato de forbarado: $6\n* Intencita forbarito: $7\n\nVi rajtas kontakti $1 aŭ alian [[{{MediaWiki:Grouppage-sysop}}|administranton]] por pridiskuti la forbaradon.\nVi ne povas uzi la 'retpoŝtan' funkcion, escepte se vi indikis validan retpoŝtan adreson en viaj [[Special:Preferences|kontaj agordoj]] kaj vi ne estas blokita uzi ĝin.\nVia IP-adreso estas $3 kaj la ID de la forbarado estas $5.\nBonvolu mencii jenajn indikojn en viaj ĉi-temaj kontaktoj.",
        "autoblockedtext": "Via IP-adreso estas aŭtomate forbarita, ĉar uzis ĝin alia uzanto, kiun baris $1.\nLa donita kialo estas:\n\n:''$2''\n\n*Komenco de forbaro: $8\n*Limdato de la blokado: $6\n*Intencis forbari uzanton: $7\n\nVi povas kontakti $1 aŭ iun ajn el la aliaj [[{{MediaWiki:Grouppage-sysop}}|administrantojn]] por diskuti la blokon.\n\nNotu, ke vi ne povas uzi la servon \"Retpoŝtu ĉi tiu uzanton\" krom se vi havas validan retpoŝt-adreson registritan en viaj [[Special:Preferences|preferojn]], kaj vi estas ne blokita kontraŭ ĝia uzado.\n\nVia nuna IP-adreso estas $3, kaj la forbaro-identigo estas $5.\nBonvolu inkluzivi tiujn detalojn en iuj ajn demandoj kiun vi farus.",
+       "systemblockedtext": "Via salutnomo aŭ IPa adreso estis aŭtomate forbarita de MediaWiki.\nLa kialo donita estas:\n\n:<em>$2</em>\n\n* Komenco de forbaro: $8\n* Eksvalidiĝo de forbaro: $6\n* Intenca forbarulo: $7\n\nVia nuna IPa adreso estas $3.\nBonvolu inkluzivi ĉiuj supraj detaloj en ajnaj demandoj vi faras.",
        "blockednoreason": "neniu kialo estis donita",
        "whitelistedittext": "Vi devas $1 por redakti paĝojn.",
        "confirmedittext": "Vi devas konfirmi vian retpoŝtan adreson antaŭ ol redakti paĝojn. Bonvolu agordi kaj validigi vian retadreson per viaj [[Special:Preferences|preferoj]].",
        "search-external": "Ekstera serĉo",
        "searchdisabled": "<p>Oni provizore malŝaltis serĉadon per la plenteksta\nindekso pro troŝarĝita servilo. Intertempe, vi povas serĉi per <i>guglo</i> aŭ per <i>jahu!</i>:</p>",
        "search-error": "Okazis eraro dum serĉado: $1",
+       "search-warning": "Okazis eraron dum serĉado: $1",
        "preferences": "Preferoj",
        "mypreferences": "Preferoj",
        "prefs-edits": "Nombro de redaktoj:",
        "prefs-help-recentchangescount": "Ĉi tiu inkluzivas lastajn ŝanĝojn, paĝajn historiojn, kaj protokolojn.",
        "prefs-help-watchlist-token2": "Tio estas la sekreta ŝlosilo al la retfluo de via atentaro.\nĈiu, kiu konas ĝin, povas legi vian atentaron. Do, ne kunhavigu ĝin.\nSe vi devas, [[Special:ResetTokens|vi povas rekomencigi ĝin]].",
        "savedprefs": "Viaj preferoj estas konservitaj.",
-       "savedrights": "La uzanto-rajtoj de {{GENDER:$1|$1}} estis konservitaj.",
+       "savedrights": "La uzanto-grupoj de {{GENDER:$1|$1}} estis konservitaj.",
        "timezonelegend": "Horzono:",
        "localtime": "Loka tempo:",
        "timezoneuseserverdefault": "Uzi defaŭlton de servilo ($1)",
        "prefswarning-warning": "Vi faris ŝanĝojn al viaj agordoj, kiuj ankoraŭ ne estas konservitaj.\nSe vi foriros de tiu ĉi paĝo sen klaki al \"$1\", viaj agordoj ne estos ĝisdatigitaj.",
        "prefs-tabs-navigation-hint": "Konsileto: Vi povas uzi la maldekstran kaj dekstran sagajn klavojn por navigi inter la langetoj en la langeta listo.",
        "userrights": "Prizorgi rajtojn de uzantoj",
-       "userrights-lookup-user": "Administri grupojn de uzantoj",
+       "userrights-lookup-user": "Elekti uzanton",
        "userrights-user-editname": "Entajpu salutnomon:",
-       "editusergroup": "Redakti grupojn de {{GENDER:$1|uzanto}}",
+       "editusergroup": "Ŝargi uzantgrupojn",
        "editinguser": "Ŝanĝado de uzantorajtoj de la {{GENDER:$1|uzanto}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Vidi uzantorajtojn de {{GENDER:$1|uzanto}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Redakti grupojn de uzantoj",
+       "userrights-viewusergroup": "Vidi grupojn de uzantoj",
        "saveusergroups": "Konservi grupojn de {{GENDER:$1|uzantoj}}",
        "userrights-groupsmember": "Membro de:",
        "userrights-groupsmember-auto": "Implica membro de:",
        "action-writeapi": "uzi la skriban API-on",
        "action-delete": "forigi ĉi tiun paĝon",
        "action-deleterevision": "forigi ĉi tiun version",
-       "action-deletedhistory": "vidi la forigitan historion de ĉi tiu paĝo",
+       "action-deletelogentry": "forigi protokolerojn",
+       "action-deletedhistory": "vidi historion de forigitaj versiojn de la paĝo",
+       "action-deletedtext": "vidi tekston el forigita versio",
        "action-browsearchive": "traserĉi forigitajn paĝojn",
-       "action-undelete": "malforigi ĉi tiun paĝon",
-       "action-suppressrevision": "kontroli kaj restarigi ĉi tiun kaŝitan version",
+       "action-undelete": "malforigi paĝojn",
+       "action-suppressrevision": "kontroli kaj restarigi kaŝitajn versiojn",
        "action-suppressionlog": "vidi ĉi tiun privantan protokolon",
        "action-block": "forari ĉi tiun uzanton de redaktado",
        "action-protect": "ŝanĝi la protektan nivelon por ĉi tiu paĝo",
        "action-userrights-interwiki": "redakti la rajtojn de uzantoj en aliaj vikioj",
        "action-siteadmin": "ŝlosi aŭ malŝlosi la datumbazon",
        "action-sendemail": "sendi retpoŝtojn",
+       "action-editmyoptions": "redakti viajn preferojn",
        "action-editmywatchlist": "modifi vian atento-liston",
        "action-viewmywatchlist": "vidi vian atento-liston",
        "action-viewmyprivateinfo": "vidi viajn privatajn informojn",
        "apisandbox-continue": "Daŭrigi",
        "apisandbox-continue-clear": "Vakigi",
        "apisandbox-continue-help": "{{int:apisandbox-continue}} [https://www.mediawiki.org/wiki/API:Query#Continuing_queries daŭrigos] la lastan peton; {{int:apisandbox-continue-clear}} forviŝos parametrojn rilatajn al daŭrigo.",
+       "apisandbox-param-limit": "Enigi <kbd>max</kbd> por uzi la maksimuman limon.",
+       "apisandbox-multivalue-all-namespaces": "$1 (ĉiuj nomspacoj)",
+       "apisandbox-multivalue-all-values": "$1 (ĉiuj valoroj)",
        "booksources": "Librofontoj",
        "booksources-search-legend": "Serĉi librofontojn",
        "booksources-search": "Serĉi",
        "booksources-text": "Jen ligilaro al aliaj TTT-ejoj, kiuj vendas librojn,\nkaj/aŭ informumos pri la libro ligita.\nLa {{SITENAME}} ne estas komerce ligita al tiuj vendejoj, kaj la listo ne estu\nkomprenata kiel rekomendo aŭ reklamo.",
        "booksources-invalid-isbn": "La donata ISBN verŝajne estas nevalida; kontrolu pri erara kopiado el la originala fonto.",
+       "magiclink-tracking-rfc": "Paĝoj kiuj uzas [https://en.wikipedia.org/wiki/Help:Magic_links#RFC magiajn ligojn] por [https://eo.wikipedia.org/wiki/Request_for_Comments peto pri komentoj]",
+       "magiclink-tracking-rfc-desc": "Ĉi tiu paĝo uzas magiajn ligojn por [https://eo.wikipedia.org/wiki/Request_for_Comments peto pri komentoj]. Vidi [https://www.mediawiki.org/wiki/special:MyLanguage/Helpo:Magiaj_ligoj mediawiki.org] pri kiel migri.",
+       "magiclink-tracking-pmid": "Paĝoj kiuj uzas magiajn ligojn por PubMed",
+       "magiclink-tracking-pmid-desc": "Ĉi tiu paĝo uzas PubMed-aj magiaj ligoj. Vidi [https://www.mediawiki.org/wiki/special:MyLanguage/Helpo:Magiaj_ligoj mediawiki.org] pri kiel migri.",
+       "magiclink-tracking-isbn": "Paĝoj kiuj uzas ISBNajn magiajn ligojn",
+       "magiclink-tracking-isbn-desc": "Ĉi tiu paĝo uzas ISBNajn magiajn ligojn. Vidi [https://www.mediawiki.org/wiki/special:MyLanguage/Helpo:Magiaj_ligoj mediawiki.org] pri kiel migri.",
        "specialloguserlabel": "Faranto:",
        "speciallogtitlelabel": "Celo (titolo aŭ  {{ns:user}}:salutnomo por uzanto):",
        "log": "Protokoloj",
        "activeusers-count": "$1 {{PLURAL:$1|ago|agoj}} dum la {{PLURAL:$3|lasta tago|lastaj $3 tagoj}}",
        "activeusers-from": "Montri uzantojn ekde:",
        "activeusers-groups": "Montri uzantojn apartenantajn al grupoj:",
+       "activeusers-excludegroups": "Ekskludi la uzantojn, kiuj grupanas:",
        "activeusers-noresult": "Neniuj uzantoj trovitaj.",
        "activeusers-submit": "Montri la agemajn uzantojn",
        "listgrouprights": "Gruprajtoj de uzantoj",
        "emailccsubject": "Kopio de via mesaĝo al $1: $2",
        "emailsent": "Retmesaĝo sendita",
        "emailsenttext": "Via retmesaĝo estas sendita.",
-       "emailuserfooter": "Ĉi tiu retpoŝtmesaĝo estis {{GENDER:$1|sendita}} de $1 al {{GENDER:$2|$2}} per la funkcio \"{{int:emailuser}}\" ĉe {{SITENAME}}.",
+       "emailuserfooter": "Ĉi tiu retpoŝtmesaĝo estis {{GENDER:$1|sendita}} de $1 al {{GENDER:$2|$2}} per la funkcio \"{{int:emailuser}}\" ĉe {{SITENAME}}. {{GENDER:$2|Via}} retpoŝto estos sendita rekte al la {{{{GENDER:$1|}}|originala sendinto}}, rivelanta {{GENDER:$2|via}} retpoŝta adreso al {{GENDER:$1|ili}}.",
        "usermessage-summary": "Lasanta sisteman mesaĝon.",
        "usermessage-editor": "Mesaĝanto de sistemo",
        "watchlist": "Mia atentaro",
        "modifiedarticleprotection": "ŝanĝis nivelon de protekto por \"[[$1]]\"",
        "unprotectedarticle": "forigis protektadon de \"[[$1]]\"",
        "movedarticleprotection": "movis protektadajn preferojn de \"[[$2]]\" al \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Protektis}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Ŝanĝis protektan nivelon}} por \"[[$1]]\"",
+       "unprotectedarticle-comment": "{{GENDER:$2|Forigis protekton}} por \"[[$1]]\"",
        "protect-title": "Protektante \"$1\"",
        "protect-title-notallowed": "Vidi protektadan nivelon de \"$1\"",
        "prot_1movedto2": "[[$1]] movita al [[$2]]",
        "pageinfo-length": "Paĝgrandeco (en bajtoj)",
        "pageinfo-article-id": "Paĝa identigo",
        "pageinfo-language": "Lingvo de paĝa enhavo",
+       "pageinfo-language-change": "ŝanĝi",
        "pageinfo-content-model": "Modelo de paĝoenhavo",
        "pageinfo-content-model-change": "ŝanĝi",
        "pageinfo-robot-policy": "Indeksado per robotoj",
        "patrol-log-header": "Jen protokolo de patrolitaj versioj.",
        "log-show-hide-patrol": "$1 protokolo pri patrolado",
        "log-show-hide-tag": "$1 etikedan protokolon",
+       "confirm-markpatrolled-button": "Ek!",
+       "confirm-markpatrolled-top": "Marki version $3 el $2 kiel patrolita?",
        "deletedrevision": "Forigita malnova versio $1",
        "filedeleteerror-short": "Eraro dum forigo de dosiero: $1",
        "filedeleteerror-long": "Eraroj renkontritaj kiam forigante la dosieron:\n\n$1",
        "tags-deactivate": "malaktivigi",
        "tags-hitcount": "$1 {{PLURAL:$1|ŝanĝo|ŝanĝoj}}",
        "tags-manage-no-permission": "Vi ne havas la rajton prilabori markilojn.",
-       "tags-manage-blocked": "Vi ne povas administri ŝanĝajn etikedojn dum blokita.",
+       "tags-manage-blocked": "Vi ne povas administri etikedojn de ŝanĝo dum {{GENDER:$1|vi}} estas forbaritaj.",
        "tags-create-heading": "Krei novan markilon",
        "tags-create-explanation": "Nove kreitaj etikedoj estos defaŭlte disponeblaj por uzado de uzantoj kaj robotoj.",
        "tags-create-tag-name": "Nomo de etikedo:",
        "tags-deactivate-not-allowed": "Ne eblas malaktivigi la etikedon \"$1\".",
        "tags-deactivate-submit": "Malaktivigi",
        "tags-apply-no-permission": "Vi ne havas permeson por aldoni ŝanĝo-etikedojn al viaj ŝanĝoj.",
-       "tags-apply-blocked": "Vi ne povas apliki etikedojn de ŝanĝo kune kun viaj ŝanĝoj dum blokita.",
+       "tags-apply-blocked": "Vi ne povas apliki etikedojn de ŝanĝo kune kun viaj ŝanĝoj dum {{GENDER:$1|vi}} estas forbarita.",
        "tags-apply-not-allowed-one": "La etikedon \"$1\" ne eblas aldoni permane.",
        "tags-apply-not-allowed-multi": "Ne estas permesite permane aldoni {{PLURAL:$2|jenan etikedon|jenajn etikedojn}}: $1",
        "tags-update-no-permission": "Vi ne havas permeson por aldoni aŭ forigi ŝanĝo-etikedojn de unuopaj revizioj aŭ protokoleroj.",
-       "tags-update-blocked": "Vi ne povas aldoni aŭ forigi etikedojn de ŝanĝo dum blokita.",
+       "tags-update-blocked": "Vi ne povas aldoni aŭ forigi etikedojn de ŝanĝo dum {{GENDER:$1|vi}} estas forbarita.",
        "tags-update-add-not-allowed-one": "Ne estas permesite permane aldoni la etikedon \"$1\".",
        "tags-update-add-not-allowed-multi": "Ne estas permesite permane aldoni {{PLURAL:$2|jenan etikedon|jenajn etikedojn}}: $1",
        "tags-update-remove-not-allowed-one": "Ne estas permesite permane forigi la etikedon \"$1\".",
        "htmlform-user-not-exists": "<strong>$1</strong> ne ekzistas.",
        "htmlform-user-not-valid": "<strong>$1</strong> ne estas valida salutnomo.",
        "logentry-delete-delete": "$1 forigis paĝon $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|forigis}} alidirektitan $3 per anstataŭigado",
        "logentry-delete-restore": "$1 restarigis paĝon $3",
        "logentry-delete-event": "$1 ŝanĝis videblecon de {{PLURAL:$5|protokola evento|$5 protokolaj eventoj}} je $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|ŝanĝis}} videblecon de {{PLURAL:$5|revizio|$5 reviziojn}} je paĝo $3: $4",
        "mw-widgets-dateinput-no-date": "Neniu dato elektita",
        "mw-widgets-dateinput-placeholder-day": "JJJJ-MM-TT",
        "mw-widgets-dateinput-placeholder-month": "JJJJ-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Serĉi aŭdvidaĵojn",
+       "mw-widgets-mediasearch-noresults": "Neniuj rezultoj trovitaj",
        "mw-widgets-titleinput-description-new-page": "paĝo ankoraŭ ne ekzistas",
        "mw-widgets-titleinput-description-redirect": "alidirekti al $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Aldoni kategorion",
        "sessionmanager-tie": "Kombini diversajn tipojn de ensaluta peto ne estas permisita: $1.",
        "sessionprovider-generic": "$1 seancoj",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "kuketaj seancoj",
        "log-action-filter-contentmodel-change": "Ŝanĝo de enhavomodelon",
        "log-action-filter-contentmodel-new": "Kreo de paĝo kun ne-norma enhavomodelo",
        "log-action-filter-delete-delete": "Forviŝigado de paĝo",
+       "log-action-filter-delete-delete_redir": "Alidirekta anstataŭigo",
        "log-action-filter-delete-restore": "Malforviŝigado de paĝo",
        "log-action-filter-delete-event": "Forviŝigado de protokolo",
        "log-action-filter-delete-revision": "Forviŝigado de rivizio",
        "authmanager-authn-autocreate-failed": "Aŭtokreo de loka konto malsukcesis: $1",
        "authmanager-change-not-supported": "La provizitaj legitimaĵoj ne povas esti ŝanĝita, kiel nenio uzus ilin.",
        "authmanager-create-disabled": "kreado de kontoj estas malebligita",
-       "authmanager-create-from-login": "Por krei vian konton, bonvolu plenigi la kampojn sube.",
+       "authmanager-create-from-login": "Por krei vian konton, bonvolu plenigi la kampojn.",
        "authmanager-create-not-in-progress": "Konta kreo ne estas progresanta aŭ seanca dateno estis perdita. Bonvolu pravi denove ekde la komenco.",
        "authmanager-create-no-primary": "La provizitaj legitimaĵoj ne povus esti uzita por konta kreo.",
        "authmanager-link-no-primary": "La provizitaj legitimaĵoj ne povus esti uzita por konta ligado.",
        "usercssispublic": "Bonvolu noti: subpaĝoj en CSS ne enhavu konfidenciajn datumojn ĉar ili estas videblaj por aliaj uzantoj.",
        "restrictionsfield-badip": "Malvalida IP-adreso de la intervalo: $1",
        "restrictionsfield-label": "Permesita IP-intervalo:",
-       "restrictionsfield-help": "Unu IP-adreso aŭ CIDR-intervalo per linio. Por permesigi ĉion, uzu<br><code>0.0.0.0/0</code><br><code>::/0</code>"
+       "restrictionsfield-help": "Unu IP-adreso aŭ CIDR-intervalo per linio. Por permesigi ĉion, uzu<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "revizio $1",
+       "pageid": "Identigilo de paĝo $1"
 }
index 39f1161..4f4ddd7 100644 (file)
        "qbfind": "Buscar",
        "qbbrowse": "Navegar",
        "qbedit": "Editar",
-       "qbpageoptions": "Opciones de página",
+       "qbpageoptions": "Esta página",
        "qbmyoptions": "Mis páginas",
        "faq": "Preguntas frecuentes",
        "faqpage": "Project:Preguntas frecuentes",
        "views": "Vistas",
        "toolbox": "Herramientas",
        "tool-link-userrights": "Modificar grupos {{GENDER:$1|del usuario|de la usuaria}}",
+       "tool-link-userrights-readonly": "Ver los grupos {{GENDER:$1|del usuario|de la usuaria}}",
        "tool-link-emailuser": "Enviar un correo a {{GENDER:$1|este usuario|esta usuaria}}",
        "userpage": "Ver página de usuario",
        "projectpage": "Ver página del proyecto",
        "botpasswords-label-delete": "Borrar",
        "botpasswords-label-resetpassword": "Restablecer la contraseña",
        "botpasswords-label-grants": "Permisos aplicables:",
-       "botpasswords-help-grants": "Cada concesión le da acceso a los permisos listados que el usuario ya posea. Véase la [[Special:ListGrants|lista de concesiones]] para más información.",
+       "botpasswords-help-grants": "Cada concesión le da acceso a los permisos listados que el usuario ya posea. Habilitar una concesión aquí no proporciona acceso a ningún permiso que tu cuenta de usuario no tendría de otra manera. Véase la [[Special:ListGrants|lista de concesiones]] para más información.",
        "botpasswords-label-grants-column": "Concedido",
        "botpasswords-bad-appid": "El nombre del bot \"$1\" no es válido.",
        "botpasswords-insert-failed": "No se pudo agregar el nombre del bot \"$1\". ¿Ya ha sido añadido?",
        "blockedtitle": "El usuario está bloqueado",
        "blockedtext": "<strong>Tu nombre de usuario o dirección IP ha sido bloqueada.</strong>\n\nEl bloqueo lo hizo $1.\nLa razón dada es <em>$2</em>.\n\n* Inicio del bloqueo: $8\n* Caducidad del bloqueo: $6\n* Bloqueo destinado a: $7\n\nPuedes contactar a $1 o con otro de los [[{{MediaWiki:Grouppage-sysop}}|administradores]] para discutir el bloqueo.\nNo puedes utilizar la función «enviar correo electrónico a este usuario» a menos que tengas una dirección de correo electrónico válida registrada en tus [[Special:Preferences|preferencias de usuario]] y la función no haya sido también bloqueada.\n\nTu dirección IP actual es $3, y el identificador del bloqueo es #$5.\nIncluye todos los datos aquí mostrados en cualquier consulta que hagas.",
        "autoblockedtext": "Tu dirección IP ha sido bloqueada automáticamente porque fue utilizada por otro usuario, que resultó bloqueado por $1.\nEl motivo dado es el siguiente:\n\n:<em>$2</em>\n\n* Inicio del bloqueo: $8\n* Caducidad del bloqueo: $6\n* Bloqueo destinado a: $7\n\nPuedes contactar con $1 o con otro de los [[{{MediaWiki:Grouppage-sysop}}|administradores]] para discutir el bloqueo.\n\nTen en cuenta que no puedes utilizar la función «enviar correo electrónico a este usuario» a menos que tengas una dirección de correo electrónico válida registrada en tus [[Special:Preferences|preferencias de usuario]] y la función no haya sido también bloqueada.\n\nTu dirección IP actual es $3, y el identificador del bloqueo es #$5.\nIncluye todos los datos aquí mostrados en cualquier consulta que hagas.",
+       "systemblockedtext": "Tu nombre de usuario o dirección IP ha sido bloqueado automáticamente por el software MediaWiki.\nLa razón dada es:\n\n:<em>$2</em>\n\n* Inicio del bloqueo: $8\n* Caducidad de bloqueo: $6\n* Destinatario del bloqueo: $7\n\nTu dirección IP actual es $3.\nPor favor, incluye todos los datos aquí mostrados en cualquier consulta que hagas.",
        "blockednoreason": "no se ha especificado el motivo",
        "whitelistedittext": "Tienes que $1 para editar páginas.",
        "confirmedittext": "Debes confirmar tu dirección de correo electrónico antes de poder editar páginas. Por favor, configura y confirma tu dirección de correo a través de tus [[Special:Preferences|preferencias de usuario]].",
        "search-external": "Búsqueda externa",
        "searchdisabled": "Las búsquedas en {{SITENAME}} están desactivadas.\nMientras tanto puedes buscar mediante Google, pero ten en cuenta que sus índices relativos a {{SITENAME}} pueden estar desactualizados.",
        "search-error": "Ha ocurrido un error al buscar: $1",
+       "search-warning": "Se ha producido un aviso al hacer la búsqueda: $1",
        "preferences": "Preferencias",
        "mypreferences": "Preferencias",
        "prefs-edits": "Cantidad de ediciones:",
        "prefs-help-recentchangescount": "Esto incluye cambios recientes, historiales de páginas y registros.",
        "prefs-help-watchlist-token2": "Esta es la clave secreta del canal de suscripción de tu lista de seguimiento.\nCualquier persona que la conozca podría leer tu lista, así que no la compartas.\n[[Special:ResetTokens|Pulsa aquí si necesitas restablecerla]].",
        "savedprefs": "Se han guardado tus preferencias.",
-       "savedrights": "Se han guardado los permisos de {{GENDER:$1|$1}}.",
+       "savedrights": "Se han guardado los grupos de {{GENDER:$1|usuario|usuaria}} de $1.",
        "timezonelegend": "Huso horario:",
        "localtime": "Hora local:",
        "timezoneuseserverdefault": "Usar la hora del servidor ($1)",
        "prefswarning-warning": "Has hecho cambios en tus preferencias que todavía no se han guardado. Si sales de esta página sin pulsar en «$1» no se actualizarán las preferencias.",
        "prefs-tabs-navigation-hint": "Sugerencia: Puede utilizar las teclas de flecha izquierda y derecha para navegar entre las pestañas de la lista de pestañas.",
        "userrights": "Gestión de permisos de usuario",
-       "userrights-lookup-user": "Configurar grupos de usuarios",
+       "userrights-lookup-user": "Selecciona una cuenta de usuario",
        "userrights-user-editname": "Escribe un nombre de usuario:",
-       "editusergroup": "Modificar grupos {{GENDER:$1|del usuario|de la usuaria}}",
+       "editusergroup": "Cargar grupos de usuarios",
        "editinguser": "Cambio de los permisos {{GENDER:$1|del usuario|de la usuaria}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modificar grupos {{GENDER:$1|del usuario| de la usuaria}}",
+       "userrights-viewusergroup": "Ver grupos de usuarios",
        "saveusergroups": "Guardar grupos {{GENDER:$1|del usuario|de la usuaria}}",
        "userrights-groupsmember": "Miembro de:",
        "userrights-groupsmember-auto": "Miembro implícito de:",
        "right-upload": "Subir archivos",
        "right-reupload": "Subir una nueva versión de un archivo existente",
        "right-reupload-own": "Subir una nueva versión de un archivo creado por uno mismo",
-       "right-reupload-shared": "Sobreescribir localmente archivos del repositorio multimedia",
+       "right-reupload-shared": "Sobrescribir localmente archivos presentes en el repositorio multimedia compartido",
        "right-upload_by_url": "Subir un archivo a traves de un URL",
        "right-purge": "Purgar la caché en el servidor sin tener que dar confirmación",
        "right-autoconfirmed": "No resultar afectado por los límites de frecuencia de edición para las IP",
        "action-writeapi": "utilizar la API de escritura",
        "action-delete": "borrar esta página",
        "action-deleterevision": "eliminar revisiones",
-       "action-deletedhistory": "ver el historial borrado de esta página",
+       "action-deletelogentry": "borrar entradas del registro",
+       "action-deletedhistory": "ver el historial de ediciones borradas de una página",
+       "action-deletedtext": "ver texto de revisión borrada",
        "action-browsearchive": "buscar páginas borradas",
-       "action-undelete": "recuperar esta página",
-       "action-suppressrevision": "revisar y restaurar esta revisión oculta",
+       "action-undelete": "restaurar páginas",
+       "action-suppressrevision": "revisar y restaurar revisiones ocultas",
        "action-suppressionlog": "ver este registro privado",
        "action-block": "bloquear a este usuario para que no edite",
        "action-protect": "cambiar los niveles de protección para esta página",
        "uploadstash-errclear": "Falló el borrado de los archivos.",
        "uploadstash-refresh": "Actualizar la lista de archivos",
        "uploadstash-thumbnail": "ver miniatura",
+       "uploadstash-exception": "No se pudo almacenar la carga en el área provisional ($1): «$2».",
        "invalid-chunk-offset": "Desplazamiento inválido del fragmento",
        "img-auth-accessdenied": "Acceso denegado",
        "img-auth-nopathinfo": "Falta PATH_INFO.\nEl servidor no está configurado para proporcionar esta información.\nEs posible que esté basado en CGI y que no sea compatible con img_auth.\nConsulte https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Image_Authorization.",
        "apisandbox-continue-clear": "Vaciar",
        "apisandbox-param-limit": "Escribe <kbd>max</kbd> para usar el límite máximo.",
        "apisandbox-multivalue-all-namespaces": "$1 (Todos los espacios de nombres)",
+       "apisandbox-multivalue-all-values": "$1 (Todos los valores)",
        "booksources": "Fuentes de libros",
        "booksources-search-legend": "Buscar fuentes de libros",
        "booksources-search": "Buscar",
        "cachedspecial-refresh-now": "Ver lo más reciente.",
        "categories": "Categorías",
        "categories-submit": "Mostrar",
-       "categoriespagetext": "Las siguientes {{PLURAL:$1|categoría contiene|categorías contienen}} páginas o medios.\nNo se muestran aquí las [[Special:UnusedCategories|categorías sin uso]].\nVéase también las [[Special:WantedCategories|categorías requeridas]].",
+       "categoriespagetext": "Las siguientes {{PLURAL:$1|categoría contiene|categorías contienen}} páginas o medios.\nNo se muestran aquí las [[Special:UnusedCategories|categorías sin uso]].\nVéanse también las [[Special:WantedCategories|categorías requeridas]].",
        "categoriesfrom": "Mostrar categorías que empiecen por:",
        "deletedcontributions": "Contribuciones borradas de usuario",
        "deletedcontributions-title": "Contribuciones borradas de usuario",
        "emailccsubject": "Copia de tu mensaje a $1: $2",
        "emailsent": "Correo electrónico enviado",
        "emailsenttext": "Se ha enviado tu mensaje de correo electrónico.",
-       "emailuserfooter": "Este correo electrónico fue {{GENDER:$1|enviado}} por $1 a {{GENDER:$2|$2}} a través de la función «{{int:emailuser}}» en {{SITENAME}}.",
+       "emailuserfooter": "Este correo electrónico fue {{GENDER:$1|enviado}} por $1 a {{GENDER:$2|$2}} a través de la función «{{int:emailuser}}» en {{SITENAME}}. {{GENDER:$2|Tu}} correo electrónico se enviará directamente {{GENDER:$1|al emisor|a la emisora}} original, y {{GENDER:$1|le}} revelará {{GENDER:$2|tu}} dirección de correo electrónico.",
        "usermessage-summary": "Dejando un mensaje de sistema.",
        "usermessage-editor": "Mensajero del sistema",
        "watchlist": "Lista de seguimiento",
        "pageinfo-length": "Longitud de la página (en bytes)",
        "pageinfo-article-id": "Identificador de la página",
        "pageinfo-language": "Idioma de la página",
+       "pageinfo-language-change": "cambiar",
        "pageinfo-content-model": "Modelo de contenido de la página",
        "pageinfo-content-model-change": "cambiar",
        "pageinfo-robot-policy": "Indización por robots",
        "newimages-showbots": "Mostrar cargas de bots",
        "newimages-hidepatrolled": "Ocultar las subidas verificadas",
        "noimages": "No hay nada que ver.",
+       "gallery-slideshow-toggle": "Alternar las miniaturas",
        "ilsubmit": "Buscar",
        "bydate": "por fecha",
        "sp-newimages-showfrom": "Mostrar archivos nuevos empezando desde $2, $1",
        "htmlform-user-not-exists": "<strong>$1</strong> no existe.",
        "htmlform-user-not-valid": "<strong>$1</strong> no es un nombre de usuario válido.",
        "logentry-delete-delete": "$1 {{GENDER:$2|borró}} la página $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|borró}} la redirección $3 con un traslado",
        "logentry-delete-restore": "$1 restauró la página «$3»",
        "logentry-delete-event": "$1 {{GENDER:$2|modificó}} la visibilidad de {{PLURAL:$5|un evento|$5 eventos}} del registro en $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|modificó}} la visibilidad de {{PLURAL:$5|una revisión |$5 revisiones}} en la página  $3: $4",
        "api-error-empty-file": "El archivo que enviaste estaba vacío.",
        "api-error-emptypage": "No se pueden crear páginas nuevas que estén vacías.",
        "api-error-fetchfileerror": "Error interno: Algo salió mal mientras se obtenía el archivo.",
-       "api-error-fileexists-forbidden": "Ya existe el archivo \"$1\" y no se puede sobreescribir.",
-       "api-error-fileexists-shared-forbidden": "Ya existe \"$1\" en el repositorio de archivos compartidos y no se puede sobreescribir.",
+       "api-error-fileexists-forbidden": "Ya existe un archivo con el nombre «$1» y no se puede sobrescribir.",
+       "api-error-fileexists-shared-forbidden": "Ya existe un archivo con el nombre «$1» en el repositorio de archivos compartido y no se puede sobrescribir.",
        "api-error-file-too-large": "El archivo que enviaste era demasiado grande.",
        "api-error-filename-tooshort": "El nombre de archivo es demasiado corto.",
        "api-error-filetype-banned": "Este tipo de archivo está prohibido.",
        "mw-widgets-dateinput-no-date": "Ninguna fecha seleccionada",
        "mw-widgets-dateinput-placeholder-day": "AAAA-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "AAAA-MM",
+       "mw-widgets-mediasearch-input-placeholder": "Buscar multimedia",
+       "mw-widgets-mediasearch-noresults": "No se han encontrado resultados.",
        "mw-widgets-titleinput-description-new-page": "la página aún no existe",
        "mw-widgets-titleinput-description-redirect": "redirigir a $1",
        "mw-widgets-categoryselector-add-category-placeholder": "Agregar una categoría...",
        "log-action-filter-contentmodel-change": "Cambio de modelo de contenido",
        "log-action-filter-contentmodel-new": "Creación de página con modelo de contenidos no estándar",
        "log-action-filter-delete-delete": "Eliminación de páginas",
-       "log-action-filter-delete-delete_redir": "Sobreescribir la redirección",
+       "log-action-filter-delete-delete_redir": "Sobrescritura de la redirección",
        "log-action-filter-delete-restore": "Restauración de páginas",
        "log-action-filter-delete-event": "Eliminación de registros",
        "log-action-filter-delete-revision": "Eliminación de revisión",
        "usercssispublic": "Recuerda: las subpáginas CSS no deberían contener datos confidenciales, pues otros usuarios los pueden ver.",
        "restrictionsfield-badip": "Dirección o intervalo IP no válidos: $1",
        "restrictionsfield-label": "Intervalos de IP permitidos:",
-       "restrictionsfield-help": "Una dirección IP o intervalo de CIDR por renglón. Para activar todo, utiliza<br><code>0.0.0.0/0</code><br><code>::/0</code>"
+       "restrictionsfield-help": "Una dirección IP o intervalo de CIDR por renglón. Para activar todo, utiliza<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "revisión $1",
+       "pageid": "ID de página $1"
 }
index f4895a3..0ab9653 100644 (file)
        "watchnologin": "Ei ole sisse logitud",
        "addwatch": "Lisa jälgimisloendisse",
        "addedwatchtext": "\"[[:$1]]\" ja selle arutelulehekülg on lisatud sinu [[Special:Watchlist|jälgimisloendisse]].",
+       "addedwatchtext-talk": "\"[[:$1]]\" ja sellega seotud lehekülg on lisatud sinu [[Special:Watchlist|jälgimisloendisse]].",
        "addedwatchtext-short": "Lehekülg \"$1\" on lisatud sinu jälgimisloendisse.",
        "removewatch": "Eemalda jälgimisloendist",
        "removedwatchtext": "\"[[:$1]]\" ja selle arutelulehekülg on [[Special:Watchlist|jälgimisloendist]] eemaldatud.",
+       "removedwatchtext-talk": "\"[[:$1]]\" ja sellega seotud lehekülg on sinu [[Special:Watchlist|jälgimisloendist]] eemaldatud.",
        "removedwatchtext-short": "Lehekülg \"$1\" on eemaldatud sinu jälgimisloendist.",
        "watch": "Jälgi",
        "watchthispage": "Jälgi seda lehekülge",
        "modifiedarticleprotection": "muutis lehekülje \"[[$1]]\" kaitsemäära",
        "unprotectedarticle": "eemaldas lehekülje \"[[$1]]\" kaitse",
        "movedarticleprotection": "teisaldas kaitsesätted leheküljelt \"[[$2]]\" leheküljele \"[[$1]]\"",
+       "protectedarticle-comment": "{{GENDER:$2|Kaitsti}} \"[[$1]]\"",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|Muudeti}} lehekülje \"[[$1]]\" kaitsetase",
+       "unprotectedarticle-comment": "{{GENDER:$2|Eemaldati}} lehekülje \"[[$1]]\" kaitse",
        "protect-title": "Lehekülje \"$1\" kaitsemäära muutmine",
        "protect-title-notallowed": "Lehekülje \"$1\" kaitsemäära vaatamine",
        "prot_1movedto2": "Lehekülg \"[[$1]]\" teisaldatud pealkirja \"[[$2]]\" alla",
        "move-page": "Lehekülje \"$1\" teisaldamine",
        "move-page-legend": "Lehekülje teisaldamine",
        "movepagetext": "Allolevat vormi kasutades saad lehekülje ümber nimetada. Lehekülje ajalugu tõstetakse uue pealkirja alla automaatselt.\nPraeguse pealkirjaga leheküljest saab ümbersuunamislehekülg uuele leheküljele.\nSaad senisele pealkirjale viitavad ümbersuunamised automaatselt parandada.\nKui sa seda ei tee, kontrolli, et teisaldamise tõttu ei jää maha [[Special:DoubleRedirects|kahekordseid]] ega [[Special:BrokenRedirects|katkiseid ümbersuunamisi]].\nSinu kohus on hoolitseda selle eest, et kõik jääks toimima, nagu ette nähtud.\n\nPane tähele, et lehekülge <strong>ei teisaldata</strong> juhul, kui uue pealkirjaga lehekülg on juba olemas. Erandiks on juhud, kui viimane on redigeerimisajaloota ümbersuunamislehekülg.\nSee tähendab, et kogemata ei saa üle kirjutada juba olemasolevat lehekülge, kuid saab ebaõnnestunud ümbernimetamise tagasi pöörata.\n\n<strong>Märkus:</strong>\nTegu võib olla väga loetava lehekülje jaoks tõsise ja ootamatu muudatusega;\nenne jätkamist teadvusta palun tagajärgi.",
-       "movepagetext-noredirectfixer": "Allolevat vormi kasutades saad lehekülje ümber nimetada. Lehekülje ajalugu tõstetakse uue pealkirja alla automaatselt.\nPraeguse pealkirjaga leheküljest saab ümbersuunamislehekülg uuele leheküljele.\nKontrolli, et teisaldamise tõttu ei jää maha [[Special:DoubleRedirects|kahekordseid]] ega [[Special:BrokenRedirects|katkiseid ümbersuunamisi]].\nSinu kohus on hoolitseda selle eest, et kõik jääks toimima, nagu ette nähtud.\n\nPane tähele, et lehekülge <strong>ei teisaldata</strong> juhul, kui uue pealkirjaga lehekülg on juba olemas. Erandiks on juhud, kui olemasolev lehekülg on tühi või redigeerimisajaloota ümbersuunamislehekülg.\nSee tähendab, et kogemata ei saa üle kirjutada juba olemasolevat lehekülge, kuid saab ebaõnnestunud ümbernimetamise tagasi pöörata.\n\n<strong>Note:</strong>\nTegu võib olla väga loetava lehekülje jaoks tõsise ja ootamatu muudatusega;\nenne jätkamist teadvusta palun tagajärgi.",
+       "movepagetext-noredirectfixer": "Allolevat vormi kasutades saad lehekülje ümber nimetada. Lehekülje ajalugu tõstetakse uue pealkirja alla automaatselt.\nPraeguse pealkirjaga leheküljest saab ümbersuunamislehekülg uuele leheküljele.\nKontrolli, et teisaldamise tõttu ei jää maha [[Special:DoubleRedirects|kahekordseid]] ega [[Special:BrokenRedirects|katkiseid ümbersuunamisi]].\nSinu kohus on hoolitseda selle eest, et kõik jääks toimima, nagu ette nähtud.\n\nPane tähele, et lehekülge <strong>ei teisaldata</strong> juhul, kui uue pealkirjaga lehekülg on juba olemas. Erandiks on juhud, kui olemasolev lehekülg on tühi või redigeerimisajaloota ümbersuunamislehekülg.\nSee tähendab, et kogemata ei saa üle kirjutada juba olemasolevat lehekülge, kuid saab ebaõnnestunud ümbernimetamise tagasi pöörata.\n\n<strong>Hoiatus!</strong>\nTegu võib olla väga loetava lehekülje jaoks tõsise ja ootamatu muudatusega;\nenne jätkamist teadvusta palun tagajärgi.",
        "movepagetalktext": "Kui märgid selle ruudu, teisaldatakse arutelulehekülg automaatselt uue pealkirja alla. Seda välja arvatud juhul, kui uue pealkirja all on juba arutelulehekülg, mis pole tühi.\n\nSel juhul saad lehekülje soovi korral käsitsi teisaldada või liita.",
        "moveuserpage-warning": "'''Hoiatus:''' Oled teisaldamas kasutajalehekülge. Pane tähele, et teisaldatakse ainult lehekülg ja kasutajat '''ei''' nimetata ümber.",
        "movecategorypage-warning": "<strong>Hoiatus:</strong> Oled teisaldamas kategoorialehekülge. Pane palun tähele, et teisaldatakse vaid see lehekülg ja ühtegi vanas kategoorias sisalduvat lehekülge <em>ei</em> kategoriseerita ümber uude kategooriasse.",
        "export-download": "Salvesta failina",
        "export-templates": "Kaasa mallid",
        "export-pagelinks": "Kaasan viidatud lehed kuni tasemeni",
+       "export-manual": "Käsitsi lisatud leheküljed:",
        "allmessages": "Kõik süsteemi sõnumid",
        "allmessagesname": "Nimi",
        "allmessagesdefault": "Vaiketekst",
        "newimages-legend": "Filter",
        "newimages-label": "Failinimi (või selle osa):",
        "newimages-showbots": "Näita robotite üles laaditud faile",
+       "newimages-hidepatrolled": "Peida kontrollitud failid",
        "noimages": "Uusi pilte ei ole.",
        "gallery-slideshow-toggle": "Lülita pisipildid ümber",
        "ilsubmit": "Otsi",
        "watchlistedit-clear-done": "Sinu jälgimisloend on tühjendatud.",
        "watchlistedit-clear-removed": "{{PLURAL:$1|Üks pealkiri|$1 pealkirja}} eemaldati:",
        "watchlistedit-too-many": "Pealkirju on siin kuvamiseks liiga palju.",
-       "watchlisttools-clear": "Tühjenda jälgimisloend",
+       "watchlisttools-clear": "tühjenda jälgimisloend",
        "watchlisttools-view": "näita vastavaid muudatusi",
        "watchlisttools-edit": "vaata ja redigeeri jälgimisloendit",
        "watchlisttools-raw": "redigeeri jälgimisloendi toorandmeid",
index 5c5d846..53abf81 100644 (file)
        "yourdomainname": "Zure domeinua",
        "password-change-forbidden": "Ezin duzu pasahitzarik aldatu wiki honetan.",
        "externaldberror": "Kanpoko datu-base autentifikazio errorea gertatu da edo ez duzu zure kanpo kontua eguneratzeko baimenik.",
-       "login": "Saioa hasi",
-       "nav-login-createaccount": "Saioa hasi / kontua sortu",
+       "login": "Hasi saioa",
+       "nav-login-createaccount": "Hasi saioa / sortu kontua",
        "userlogin": "Saioa hasi / kontua sortu",
        "userloginnocreate": "Hasi saioa",
        "logout": "Saioa itxi",
        "nologinlink": "Kontua sortu",
        "createaccount": "Kontua sortu",
        "gotaccount": "Baduzu erabiltzaile kontua? '''$1'''.",
-       "gotaccountlink": "Saioa hasi",
+       "gotaccountlink": "Hasi saioa",
        "userlogin-resetlink": "Saioa hasteko datuak ahaztu dituzu?",
        "userlogin-resetpassword-link": "Zure pasahitza ahaztu duzu?",
        "userlogin-helplink2": "Saioa hasteko laguntza",
        "enotif_body_intro_deleted": "{{SITENAME}}(e)ko $1 orrialdea {{GENDER:$2|ezabatu}} du $2 erabiltzaileak $PAGEEDITDATE datan, ikus $3.",
        "enotif_body_intro_created": "{{SITENAME}}(e)ko $1 orrialdea {{GENDER:$2|sortu}} du $2 erabiltzaileak $PAGEEDITDATE datan, ikus $3 oraingo bertsiorako.",
        "enotif_body_intro_moved": "{{SITENAME}}(e)ko $1 orrialdea {{GENDER:$2|mugitu}} du $2 erabiltzaileak $PAGEEDITDATE datan, ikus $3 oraingo bertsiorako.",
-       "enotif_body_intro_restored": "{{SITENAME}}(e)ko $1 orrialdea {{GENDER:$2|berrezarri}} du $2 erabiltzaileak $PAGEEDITDATE datan, ikus $3 oraingo bertsiorako.",
+       "enotif_body_intro_restored": "{{SITENAME}} guneko «$1» orria {{GENDER:$2|lehengoratu}} du $2 administratzaileak $PAGEEDITDATE datan. Oraingo bertsioa ikusteko, zoaz helbide honetara: $3.",
        "enotif_body_intro_changed": "{{SITENAME}}(e)ko $1 orrialdea {{GENDER:$2|aldatu}} du $2 erabiltzaileak $PAGEEDITDATE datan, ikus $3 oraingo bertsiorako.",
        "enotif_lastvisited": "Ikus «$1» zure azken bisitaz geroztik izandako aldaketa guztiak ikusteko.",
        "enotif_lastdiff": "Jo $1(e)ra aldaketa hau ikusteko.",
        "specialpages-note": "* Orri berezi arruntak.\n* <strong class=\"mw-specialpagerestricted\">Mugatutako orri bereziak.</strong>",
        "specialpages-group-maintenance": "Mantentze-oharrak",
        "specialpages-group-other": "Beste orri berezi batzuk",
-       "specialpages-group-login": "Saioa hasi / kontua sortu",
+       "specialpages-group-login": "Hasi saioa / sortu kontua",
        "specialpages-group-changes": "Aldaketa berriak eta erregistroak",
        "specialpages-group-media": "Artxiboen orriak",
        "specialpages-group-users": "Erabiltzaileak eta eskumenak",
        "htmlform-user-not-exists": "<strong>$1</strong> ez da existitzen.",
        "htmlform-user-not-valid": "<strong>$1</strong> erabiltzaile izena ezin da erabili.",
        "logentry-delete-delete": "$1 {{GENDER:$2|wikilariak}} «$3» orria ezabatu du",
-       "logentry-delete-restore": "$1(e)k $3 orrialdea {{GENDER:$2|berrezarri}} du",
+       "logentry-delete-restore": "$1 administratzaileak «$3» orria {{GENDER:$2|lehengoratu}} du",
        "logentry-delete-event": "$1 wikilariak ikusgaitasuna {{{{GENDER:$2|}}|aldatu}} {{PLURAL:$5|dio erregistroko sarrera bati|die erregistroko $5 sarrerari}}, $3 orrian: $4",
        "logentry-delete-revision": "$1 erabiltzaileak {{PLURAL:$5|berrikuste baten|$5 berrikusteren}} ikusgaitasuna aldatu du «$3» orrian: $4",
        "logentry-suppress-delete": "$1 erabiltzaileak $3 orrialdea {{GENDER:$2|ezabatu}} du",
index 3a773d1..c269be1 100644 (file)
        "nstab-special": "صفحهٔ ویژه",
        "nstab-project": "صفحهٔ پروژه",
        "nstab-image": "پرونده",
-       "nstab-mediawiki": "پیام",
+       "nstab-mediawiki": "Ù¾Û\8cغاÙ\85",
        "nstab-template": "الگو",
        "nstab-help": "صفحهٔ راهنما",
        "nstab-category": "رده",
index 35806aa..fdd94bc 100644 (file)
        "addwatch": "Lisää tarkkailulistalle",
        "addedwatchtext": "\"[[:$1]]\" ja sen keskustelusivu on lisätty [[Special:Watchlist|tarkkailulistallesi]].",
        "addedwatchtext-talk": "\"[[:$1]]\" ja siihen liittyvä sivu on lisätty [[Special:Watchlist|tarkkailulistallesi]].",
-       "addedwatchtext-short": "Sivu ”$1” on lisätty tarkkailulistallesi.",
+       "addedwatchtext-short": "Sivu \"$1\" on lisätty tarkkailulistallesi.",
        "removewatch": "Poista tarkkailulistalta",
        "removedwatchtext": "\"[[:$1]]\" ja sen keskustelusivu on poistettu [[Special:Watchlist|tarkkailulistaltasi]].",
        "removedwatchtext-talk": "\"[[:$1]]\" ja siihen liittyvä sivu on poistettu [[Special:Watchlist|tarkkailulistaltasi]].",
        "tags-deactivate": "ota pois käytöstä",
        "tags-hitcount": "$1 {{PLURAL:$1|muutos|muutosta}}",
        "tags-manage-no-permission": "Sinulla ei ole oikeutta käsitellä merkkauksia.",
-       "tags-manage-blocked": "Et voi hallita muokkausmerkkauksia kun {{GENDER:$1|olet}} estettynä.",
+       "tags-manage-blocked": "Et voi hallita muokkausmerkkauksia, kun {{GENDER:$1|olet}} estettynä.",
        "tags-create-heading": "Luo uusi merkkaus",
        "tags-create-explanation": "Oletuksena on, että uutena luodut merkkaukset tulevat käyttäjien ja bottien käyttöön.",
        "tags-create-tag-name": "Merkkauksen nimi:",
        "tags-deactivate-not-allowed": "Ei ole mahdollista poistaa käytöstä merkkausta \"$1\".",
        "tags-deactivate-submit": "Poista käytöstä",
        "tags-apply-no-permission": "Sinulla ei ole oikeutta käyttää merkkauksia muutostesi yhteydessä.",
-       "tags-apply-blocked": "Et voi asettaa merkkauksia muutostesi yhteyteen kun {{GENDER:$1|olet}} estettynä.",
+       "tags-apply-blocked": "Et voi asettaa merkkauksia muutostesi yhteyteen, kun {{GENDER:$1|olet}} estettynä.",
        "tags-apply-not-allowed-one": "Merkkausta \"$1\" ei ole sallittua asettaa käsin.",
        "tags-apply-not-allowed-multi": "Seuraavia {{PLURAL:$2|merkkauksia}} ei ole sallittua asettaa käsin: $1",
        "tags-update-no-permission": "Sinulla ei ole oikeutta lisätä tai poistaa merkkauksia yksittäisissä sivuversioissa tai lokimerkinnöissä.",
-       "tags-update-blocked": "Et voi lisätä tai poistaa merkkauksia kun {{GENDER:$1|olet}} estettynä.",
+       "tags-update-blocked": "Et voi lisätä tai poistaa merkkauksia, kun {{GENDER:$1|olet}} estettynä.",
        "tags-update-add-not-allowed-one": "Merkkausta \"$1\" ei ole sallittua asettaa käsin.",
        "tags-update-add-not-allowed-multi": "Seuraavia {{PLURAL:$2|merkkauksia}} ei ole sallittua asettaa käsin: $1",
        "tags-update-remove-not-allowed-one": "Merkkausta \"$1\" ei ole sallittua poistaa.",
        "log-action-filter-contentmodel-change": "Sisältömallin muuttaminen",
        "log-action-filter-contentmodel-new": "Luotu sivu, jossa on poikkeava Sisältömalli",
        "log-action-filter-delete-delete": "Sivun poistaminen",
+       "log-action-filter-delete-delete_redir": "Ohjauksen päällekirjoitus",
        "log-action-filter-delete-restore": "Sivun palauttaminen",
        "log-action-filter-delete-event": "Lokimerkinnän poistaminen",
        "log-action-filter-delete-revision": "Version piilottaminen",
        "userjsispublic": "Huomio: JavaScript-alasivuilla ei tulisi olla luottamuksellisia tietoja, koska muut käyttäjät voivat nähdä ne.",
        "usercssispublic": "Huomio: CSS-alasivuilla ei tulisi olla luottamuksellisia tietoja, koska muut käyttäjät voivat nähdä ne.",
        "restrictionsfield-badip": "Virheellinen IP-osoite tai alue: $1",
-       "restrictionsfield-label": "Sallitut IP-alueet:"
+       "restrictionsfield-label": "Sallitut IP-alueet:",
+       "revid": "versio $1",
+       "pageid": "sivun tunnistenumero $1"
 }
index 19113d8..eaef8b2 100644 (file)
@@ -12,7 +12,8 @@
                        "לערי ריינהארט",
                        "아라",
                        "Macofe",
-                       "Irus"
+                       "Irus",
+                       "Fitoschido"
                ]
        },
        "tog-underline": "Undirstrika leinki:",
        "passwordreset-emaildisabled": "Teldupost funksjónir eru óvirknar á hesi wiki.",
        "passwordreset-username": "Brúkaranavn:",
        "passwordreset-domain": "Umdømi (domain):",
-       "passwordreset-capture": "Sí tann endaliga t-postin?",
-       "passwordreset-capture-help": "Um tú setir kross við henda teigin, so verður t-posturin (við fyribils loyniorðinum) vístur fyri tær og verður harumframt sendur til brúkaran.",
        "passwordreset-email": "T-post adressur:",
        "passwordreset-emailtitle": "konto upplýsingar á {{SITENAME}}",
        "passwordreset-emailtext-ip": "Onkur (óiva tú, frá IP adressu $1) hevur biðið um nullstillan av tínum loyniorði til {{SITENAME}} ($4). Fylgjandi brúkara {{PLURAL:$3|konta er|kontur eru}}\nsettar í samband við hesa t-post adressu:\n\n$2\n\n{{PLURAL:$3|Hetta fyribils loyniorðið|Hesi fyribils loyniorðini}} ganga út um {{PLURAL:$5|ein dag|$5 dagar}}.\nTú eigur at rita inn og velja eitt nýtt loyniorð nú. Um onkur annar hevur gjørt hesa umbønina, ella um tú ert komin í tankar um títt uppruna loyniorð, og tú ikki longur ynskir at broyta tað, so kanst tú síggja burtur frá hesum boðum og halda fram at brúka títt gamla loyniorð.",
        "userinvalidcssjstitle": "'''Ávaring:''' Tað er onki skinn \"$1\".\nTilevnaðar .css og .js síður brúka heiti sum byrja við lítlum bókstavi, t.d.  {{ns:user}}:Foo/vector.css í mun til {{ns:user}}:Foo/Vector.css.",
        "updated": "(Dagført)",
        "note": "'''Viðmerking:'''",
-       "previewnote": "'''Minst til at hetta bara er ein forskoðan.'''\nTínar broytingar eru ikki goymdar enn!",
+       "previewnote": "<strong>Minst til at hetta bara er ein forskoðan.</strong>\nTínar broytingar eru ikki goymdar enn!",
        "continue-editing": "Far til økið har ið tú kanst gera rættingar",
        "previewconflict": "Henda forskoðanin vísir tekstin í erva soleiðis sum hann sær út, um tú velur at goyma.",
        "session_fail_preview": "'''Orsakað! Vit kundu ikki fullføra tínar broytingar, tí tínar sessións dáta eru horvin.'''\nVinarliga royn aftur.\nUm tað enn ikki virkar, royn so [[Special:UserLogout|rita út]] og rita so inn aftur.",
        "userrights-reason": "Orsøk:",
        "userrights-no-interwiki": "Tú hevur ikki loyvi til at rætta brúkara rættindi á øðrum wikium.",
        "userrights-nodatabase": "Dátugrunnurin $1 er ikki til ella er hann ikki lokalur.",
-       "userrights-nologin": "Tú mást [[Special:UserLogin|rita inn]] sum administrator fyri at kunna áseta brúkararættindi.",
-       "userrights-notallowed": "Tú hevur ikki loyvi til at geva ella taka burtur brúkara rættindi.",
        "userrights-changeable-col": "Bólkar sum tú kanst broyta",
        "userrights-unchangeable-col": "Bólkar, ið tú ikki kanst broyta",
        "userrights-conflict": "Ósamsvar viðvíkjandi broytingum í brúkararættindum! Vinarliga endurskoða og vátta tínar broytingar.",
-       "userrights-removed-self": "Tað eydnaðist tær at taka burtur tíni egnu rættindi. Tí kanst tú ikki longur fáa atgongd til hesa síðuna.",
        "group": "Bólkur:",
        "group-user": "Brúkarar",
        "group-autoconfirmed": "Sjálvvirkandi váttaðir brúkarar",
        "right-siteadmin": "Stong og læs upp dátugrunnin",
        "right-override-export-depth": "Útflyt síður, eisini slóðaðar síður upp til eina dýpd á 5",
        "right-sendemail": "Send t-post til aðrir brúkarar",
-       "right-passwordreset": "Sí teldupostar til nullstilling av loyniorði",
        "newuserlogpage": "Brúkara logg",
        "newuserlogpagetext": "Hetta er ein listi yvir seinast stovnaðu brúkarar.",
        "rightslog": "Rættindaloggur",
index 1b352f2..8e18f5d 100644 (file)
                        "Lucas",
                        "Mabroukb",
                        "Pymouss",
-                       "Derugon"
+                       "Derugon",
+                       "Benoit Rochon"
                ]
        },
        "tog-underline": "Soulignement des liens :",
        "sort-descending": "Tri décroissant",
        "sort-ascending": "Tri croissant",
        "nstab-main": "Page",
-       "nstab-user": "Page utilisateur",
+       "nstab-user": "Page {{GENDER:{{ROOTPAGENAME}}|utilisateur|utilisatrice}}",
        "nstab-media": "Média",
        "nstab-special": "Page spéciale",
        "nstab-project": "À propos",
        "blockedtitle": "L’utilisateur est bloqué.",
        "blockedtext": "<strong>Votre compte utilisateur ou votre adresse IP a été bloqué.</strong>\n\nLe blocage a été effectué par $1.\nLa raison invoquée est la suivante : <em>$2</em>.\n\n* Début du blocage : $8\n* Expiration du blocage : $6\n* Compte bloqué : $7.\n\nVous pouvez contacter $1 ou un autre [[{{MediaWiki:Grouppage-sysop}}|administrateur]] pour en discuter.\nVous ne pouvez utiliser la fonction « {{int:emailuser}} » que si une adresse de courriel valide est spécifiée dans vos [[Special:Preferences|préférences]] et que si cette fonctionnalité n’a pas été bloquée.\nVotre adresse IP actuelle est $3 et votre identifiant de blocage est $5.\nVeuillez préciser ces indications dans toutes les requêtes que vous ferez.",
        "autoblockedtext": "Votre adresse IP a été bloquée automatiquement car elle a été utilisée par un autre utilisateur, lui-même bloqué par $1.\nLa raison invoquée est :\n\n:<em>$2:</em>\n\n* Début du blocage : $8\n* Expiration du blocage : $6\n* Compte bloqué : $7\n\nVous pouvez contacter $1 ou l’un des autres [[{{MediaWiki:Grouppage-sysop}}|administrateurs]] pour discuter de ce blocage.\n\nNotez que vous ne pourrez utiliser la fonctionnalité d’envoi de courriel que si vous avez une adresse de courriel validée dans vos [[Special:Preferences|préférences]] et que cette fonctionnalité n’a pas été désactivée.\n\nVotre adresse IP actuelle est $3, et le numéro de blocage est $5.\nVeuillez préciser ces indications dans toutes les requêtes que vous ferez.",
+       "systemblockedtext": "Votre nom d'utilisateur ou votre adresse IP ont été bloqués par MediaWiki.\nLa raison donnée est la suivante:\n\n:<em>$2</em>\n\n* Le début du blocage: $8\n* Expiration d'un délai de blocage: $6\n* Elément concerné: $7\n\nVotre adresse IP actuelle est de $3.\nVeuillez inclure tous les détails ci-dessus dans chacune des requêtes que vous faites.",
        "blockednoreason": "aucune raison donnée",
        "whitelistedittext": "Vous devez vous $1 pour avoir la permission de modifier le contenu.",
        "confirmedittext": "Vous devez confirmer votre adresse de courriel avant de modifier les pages.\nVeuillez entrer et valider votre adresse de courriel dans vos [[Special:Preferences|préférences]].",
        "ipb-confirm": "Confirmer le blocage",
        "badipaddress": "Adresse IP incorrecte",
        "blockipsuccesssub": "Blocage réussi",
-       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] a été bloqué{{GENDER:$1||e}}.<br />\nConsultez la [[Special:BlockList|liste des blocages]] pour revoir les blocages.",
+       "blockipsuccesstext": "[[Special:Contributions/$1|$1]] a été bloqué{{GENDER:$1||e}}.<br />\nConsultez la [[Special:BlockList|liste des blocages]] pour voir les utilisateurs bloqués.",
        "ipb-blockingself": "Vous êtes sur le point de bloquer votre propre compte ! Êtes-vous certain{{GENDER:||e}} de vouloir faire cela ?",
        "ipb-confirmhideuser": "Vous êtes sur le point de bloquer un utilisateur avec « cacher l'utilisateur » activé. Cela supprimera le nom de l'utilisateur dans toutes les listes et les entrées du journal. Êtes-vous sûr{{GENDER:||e}} de vouloir le faire ?",
        "ipb-confirmaction": "Si vous êtes sûr{{GENDER:||e}} de vraiment vouloir le faire, veuillez cocher le champ « {{int:ipb-confirm}} » en bas.",
        "javascripttest": "Test de JavaScript",
        "javascripttest-pagetext-unknownaction": "Action « $1 » inconnue.",
        "javascripttest-qunit-intro": "Voir [$1 la documentation de test] sur mediawiki.org.",
-       "tooltip-pt-userpage": "{{GENDER:|Votre}} page utilisateur",
+       "tooltip-pt-userpage": "Votre page {{GENDER:|utilisateur|utilisatrice}}",
        "tooltip-pt-anonuserpage": "La page utilisateur avec l'adresse IP de laquelle vous contribuez",
        "tooltip-pt-mytalk": "{{GENDER:|Votre}} page de discussion",
        "tooltip-pt-anontalk": "La page de discussion pour les contributions depuis cette adresse IP",
        "pageinfo-length": "Taille de la page (en octets)",
        "pageinfo-article-id": "Numéro de la page",
        "pageinfo-language": "Langue du contenu de la page",
+       "pageinfo-language-change": "modifier",
        "pageinfo-content-model": "Modèle de contenu de la page",
        "pageinfo-content-model-change": "modifier",
        "pageinfo-robot-policy": "Indexation par robots",
        "limitreport-postexpandincludesize-value": "$1/$2 {{PLURAL:$2|octet|octets}}",
        "limitreport-templateargumentsize": "Taille de l’argument du modèle",
        "limitreport-templateargumentsize-value": "$1/$2 {{PLURAL:$2|octet|octets}}",
-       "limitreport-expansiondepth": "Plus grande profondeur d’expansion",
+       "limitreport-expansiondepth": "Profondeur d’expansion maximale",
        "limitreport-expensivefunctioncount": "Nombre de fonctions d’analyse coûteuses",
        "expandtemplates": "Expansion des modèles",
        "expand_templates_intro": "Cette page spéciale accepte un texte wiki source et permet de réaliser récursivement l’expansion de tous les modèles qu’il contient.\nElle réalise aussi l’expansion des fonctions supportées d'analyse telles que\n<code><nowiki>{{</nowiki>#language:...}}</code> et des variables telles que\n<code><nowiki>{{</nowiki>CURRENTDAY}}</code>.\nEn fait, elle réalise l'expansion de pratiquement tout ce qui est encadré par des doubles accolades.",
        "restrictionsfield-badip": "Adresse IP ou plage non valide : $1",
        "restrictionsfield-label": "Plages IP autorisées :",
        "restrictionsfield-help": "Une adresse IP ou une plage CIDR par ligne. Pour tout activer, utiliser <br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "version $1",
        "pageid": "ID de page $1"
 }
index a9446ce..063cdae 100644 (file)
        "passwordreset-emaildisabled": "E-mail as üüb detheer Wiki ufknipset wurden.",
        "passwordreset-username": "Brükernööm:",
        "passwordreset-domain": "Domain:",
-       "passwordreset-capture": "Wel dü det e-mail nooracht uunluke?",
-       "passwordreset-capture-help": "Wan dü detheer kasche uunkrüsagst, woort det e-mail nooracht mä det nei paaswurd uunwiset an tu di brüker schüürd.",
        "passwordreset-email": "E-mail adres:",
        "passwordreset-emailtitle": "Brükerkonto aw {{SITENAME}}",
        "passwordreset-emailtext-ip": "Hoker mä det IP-Adres $1, woorskiinelk dü salew, wul hal brükerinformatsjuunen för {{SITENAME}} tusjüürd fu ($4). {{PLURAL:$3|Detdiar brükerkonto as|Jodiar brükerkontos san}} mä detdiar E-Mail-adres ferbünjen:\n\n$2\n\n{{PLURAL:$3|Detheer tidjwiis paaswurd lääpt|Joheer tidjwiis paaswurden luup}} efter {{PLURAL:$5|ään dai|$5 daar}} uf. \nDü skulst di uunmelde an en nei paaswurd iinracht. Wan hoker ööders detheer uunfraag steld hää an dü din ual paaswurd käänst, do säärst dü niks widjer onernem. Melde di ianfach widjerhen mä din ual paaswurd uun.",
        "newarticle": "(Nei)",
        "newarticletext": "Dü beest en ferwisang tu en sidj fulagt, diar't noch ei jaft.\nAm det sidj iinturachten, skriiw dan tekst uun det fial för't bewerkin iin.\nÜüb det [$1 halepsidj] fanjst dü halep.\nWan dü ütj fersen heer beest, trak ianfach üüb di <strong>turag</strong>-knoop faan dan browser.",
        "anontalkpagetext": "----''Üüb detheer sidj könst dü en ünbekäänden brüker en nooracht du. Det lääpt auer sin IP adres. IP adresen kön faan flook brükern brükt wurd. Wan dü mä detheer nooracht niks began könst, do as det ferlicht för hoker ööders mend weesen. Dü säärst niks widjer onernem. Wan dü en aanj [[Special:CreateAccount|brükerkonto iinrachst]] of di [[Special:UserLogin|uunmeldest]], komt sowat ei weder föör.",
-       "noarticletext": "Üüb detdiar sidj stäänt noch niks.\nDü könst didiar tiitel üüb ööder sidjen [[Special:Search/{{PAGENAME}}|schük]],\n<span class=\"plainlinks\">uun [{{fullurl:{{#special:Log}}|page={{FULLPAGENAMEE}}}} logbuken schük] of detdiar sidj [{{fullurl:{{FULLPAGENAME}}|action=edit}} bewerke]</span>.",
+       "noarticletext": "Üüb detdiar sidj stäänt noch niks.\nDü könst didiar tiitel üüb ööder sidjen [[Special:Search/{{PAGENAME}}|schük]],\n<span class=\"plainlinks\">uun [{{fullurl:{{#special:Log}}|page={{FULLPAGENAMEE}}}} logbuken schük] of detdiar sidj [{{fullurl:{{FULLPAGENAME}}|action=edit}} maage]</span>.",
        "noarticletext-nopermission": "Üüb detdiar sidj stäänt noch niks, oober dü mutst diar uk niks iinskriiw.\nDü könst diar üüb ööder sidjen efter [[Special:Search/{{PAGENAME}}|schük]] of a <span class=\"plainlinks\">[{{fullurl:{{#special:Log}}|page={{FULLPAGENAME}}}} logbuken uunluke].</span>",
        "missing-revision": "Det werjuun #$1 faan det sidj \"{{FULLPAGENAME}}\" jaft at ei.\n\nDet komt diar miast faan, dat en ual ferwisang stregen wurden as.\nDü könst det uun't [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} logbuk faan stregen sidjen] efterlees.",
        "userpage-userdoesnotexist": "Det brükerkonto ''$1'' as ei diar.\nWel dü detdiar sidj würelk maage/bewerke?",
        "userrights-reason": "Grünj:",
        "userrights-no-interwiki": "Dü heest ei det rocht, am brükerrochten uun ööder wikis tu feranrin.",
        "userrights-nodatabase": "Det dootenbeenk $1 jaft at ei, tumanst ei lokaal.",
-       "userrights-nologin": "Dü mutst di mä en administraator-brükerkonto [[Special:UserLogin|uunmelde]], wan dü brükerrochten feranre wel.",
-       "userrights-notallowed": "Dü heest ei det rocht, am brükerrochten tu feranrin.",
        "userrights-changeable-col": "Lasmootskapen, diar dü feranre könst",
        "userrights-unchangeable-col": "Lasmootskapen, diar dü ei feranre könst",
        "userrights-conflict": "Konflikt bi't feranrin faan brükerrochten! Du din feranrangen noch ans iin.",
-       "userrights-removed-self": "Dü heest din aanj brükerrochtem stregen. Dü könst nü ei muar üüb det sidj tugrip.",
        "group": "Skööl:",
        "group-user": "Brükern",
        "group-autoconfirmed": "Registriaret brükern",
        "right-siteadmin": "Dootenbeenk spere an eebenmaage",
        "right-override-export-depth": "Sidjen an onersidjen bit tu en jipde faan 5 eksportiare",
        "right-sendemail": "E-mails tu ööder brükern schüür",
-       "right-passwordreset": "Paaswurd faan en brüker turagsaat an det e-mail diartu uunluke",
        "right-managechangetags": "[[Special:Tags|Markiarangen]] iinracht an uun't dootenbeenk strik",
        "right-applychangetags": "[[Special:Tags|Markiarangen]] tuup mä ööder feranrangen brük",
        "right-changetags": "Feranre [[Special:Tags|markiarangen]] faan enkelt werjuunen of logbukiindracher",
        "javascripttest": "JavaScript-test",
        "javascripttest-pagetext-unknownaction": "Ünbekäänd aktjuun „$1“.",
        "javascripttest-qunit-intro": "Luke efter bi [$1 test dokumentatjuun] üüb mediawiki.org",
-       "tooltip-pt-userpage": "Din brükersidj",
+       "tooltip-pt-userpage": "{{GENDER:|Din}} brükersidj",
        "tooltip-pt-anonuserpage": "Brükersidj faan det IP-adres, faan huar ütj dü werkest",
-       "tooltip-pt-mytalk": "Din diskuschuunssidj",
+       "tooltip-pt-mytalk": "{{GENDER:|Din}} diskuschuunsidj",
        "tooltip-pt-anontalk": "Diskuschuun auer feranrangen faan detdiar IP-adres",
-       "tooltip-pt-preferences": "Min iinstelangen",
+       "tooltip-pt-preferences": "{{GENDER:|Din}} iinstelangen",
        "tooltip-pt-watchlist": "Sidjen, diar dü uun't uug behual wel",
-       "tooltip-pt-mycontris": "List mä aanj bidracher",
+       "tooltip-pt-mycontris": "List mä {{GENDER:|aanj}} bidracher",
        "tooltip-pt-login": "Wan dü di uunmeldest, heest dü muar mögelkhaiden. Dü säärst det oober ei.",
        "tooltip-pt-logout": "Ufmelde",
        "tooltip-pt-createaccount": "Wees so gud an racht en brükerkonto iin an melde di uun. Dü säärst det oober ei.",
        "tooltip-t-recentchangeslinked": "Leetst feranrangen faan sidjen, huar faan heer üüb ferwiset woort",
        "tooltip-feed-rss": "RSS-feed för detdiar sidj",
        "tooltip-feed-atom": "Atom-feed för detdiar sidj",
-       "tooltip-t-contributions": "List mä bidracher faan didiar brüker uunluke",
+       "tooltip-t-contributions": "List mä bidracher faan {{GENDER:$1|didiar brüker|detdiar brüker}} uunluke",
        "tooltip-t-emailuser": "En e-mail tu didiar brüker schüür",
        "tooltip-t-info": "Muar auer detdiar sidj",
        "tooltip-t-upload": "Datein huuchschüür",
        "feedback-thanks": "Föl soonk. Dan komentaar as üüb det sidj „[$2 $1]“ skrewen wurden.",
        "feedback-thanks-title": "Föl soonk!",
        "feedback-useragent": "Brüker-agent:",
-       "searchsuggest-search": "Schük",
+       "searchsuggest-search": "Schük uun {{SITENAME}}",
        "searchsuggest-containing": "diar banen as ...",
        "api-error-badaccess-groups": "Dü mutst nian datein tu detdiar Wiki huuchschüür.",
        "api-error-badtoken": "Intern feeler: Token as ferkiard.",
index eba3cb5..fe3e5e4 100644 (file)
        "revertmerge": "Desfacer a fusión",
        "mergelogpagetext": "A continuación hai unha lista coas fusións máis recentes do historial dunha páxina co doutra.",
        "history-title": "Historial de revisións de \"$1\"",
-       "difference-title": "Diferenzas entre revisións de \"$1\"",
+       "difference-title": "Diferenzas entre revisións de «$1»",
        "difference-title-multipage": "Diferenzas entre as páxinas \"$1\" e \"$2\"",
        "difference-multipage": "(Diferenzas entre páxinas)",
        "lineno": "Liña $1:",
        "userrights-user-editname": "Escriba un nome de usuario:",
        "editusergroup": "Cargar os grupos de usuario",
        "editinguser": "Mudando os dereitos {{GENDER:$1|do usuario|da usuaria}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Consultando os dereitos {{GENDER:$1|de usuario|de usuaria}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Editar os grupos do usuario",
        "userrights-viewusergroup": "Consultar os grupos do usuario",
        "saveusergroups": "Gardar os grupos {{GENDER:$1|do usuario|da usuaria}}",
        "recentchanges-page-removed-from-category-bundled": "[[:$1]] eliminada da categoría [[Special:WhatLinksHere/$1||esta páxina está incluída noutras páxinas]]",
        "autochange-username": "Cambio automático de MediaWiki",
        "upload": "Subir un ficheiro",
-       "uploadbtn": "Subir o ficheiro",
+       "uploadbtn": "Subir un ficheiro",
        "reuploaddesc": "Cancelar a subida e volver ao formulario de subidas",
        "upload-tryagain": "Enviar a descrición do ficheiro modificada",
        "uploadnologin": "Non accedeu ao sistema",
        "emailccsubject": "Copia da súa mensaxe para $1: $2",
        "emailsent": "Mensaxe enviada",
        "emailsenttext": "A súa mensaxe de correo electrónico foi enviada.",
-       "emailuserfooter": "$1 {{GENDER:$1|enviou}} este correo electrónico a {{GENDER:$2|$2}} mediante a función \"{{int:emailuser}}\" de {{SITENAME}}.",
+       "emailuserfooter": "$1 {{GENDER:$1|enviou}} este correo electrónico a {{GENDER:$2|$2}} mediante a función \"{{int:emailuser}}\" de {{SITENAME}}. {{GENDER:$2|A súa}} dirección de correo electrónico será enviada directamente {{GENDER:$1|ó|á}} remitente orixinal, {{GENDER:$1|revelándolle}} a {{GENDER:$2|súa}} dirección de correo.",
        "usermessage-summary": "Mensaxe deixada polo sistema.",
        "usermessage-editor": "Editor das mensaxes do sistema",
        "watchlist": "Lista de vixilancia",
        "pageinfo-length": "Lonxitude da páxina (en bytes)",
        "pageinfo-article-id": "ID da páxina",
        "pageinfo-language": "Lingua do contido da páxina",
+       "pageinfo-language-change": "cambiar",
        "pageinfo-content-model": "Modelo do contido da páxina",
        "pageinfo-content-model-change": "cambiar",
        "pageinfo-robot-policy": "Indexación por robots",
        "restrictionsfield-badip": "Enderezo IP ou rango de IP non válido: $1",
        "restrictionsfield-label": "Rangos de IP permitidos:",
        "restrictionsfield-help": "Un único enderezo IP ou rango CIDR por liña. Para habilitalos todos, utilice<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "revisión $1",
        "pageid": "identificador de páxina $1"
 }
index 1e7b346..c613bec 100644 (file)
        "subject-preview": "תצוגה מקדימה של הנושא:",
        "previewerrortext": "אירעה שגיאה בעת הניסיון להציג תצוגה מקדימה של השינויים שלך.",
        "blockedtitle": "המשתמש חסום",
-       "blockedtext": "'''שם המשתמש או כתובת ה־IP שלכם נחסמו.'''\n\nהחסימה בוצעה על ידי $1. הסיבה שניתנה לכך היא '''$2'''.\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותכם ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון על החסימה.\nאינכם יכולים להשתמש בתכונת \"שליחת דואר אלקטרוני למשתמש זה\" אם לא ציינתם כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלכם]] או אם נחסמתם משליחת דוא\"ל.\nכתובת ה־IP שלכם היא $3, ומספר החסימה שלכם הוא #$5.\nאנא ציינו את כל הפרטים הללו בכל פנייה למפעילי המערכת.",
-       "autoblockedtext": "כתובת ה־IP שלכם נחסמה באופן אוטומטי כיוון שמשתמש אחר, שנחסם על־ידי $1, השתמש בה.\nהסיבה שניתנה לחסימה היא:\n\n:<em>$2</em>\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותכם ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\n\nבאפשרותכם להשתמש בתכונת \"שליחת דואר אלקטרוני למשתמש זה\", אלא אם לא ציינתם כתובת דוא\"ל תקינה ב[[Special:Preferences|העדפות המשתמש שלכם]] או אם נחסמתם משליחת דוא\"ל.\n\nכתובת ה־IP שלכם היא $3, ומספר החסימה שלכם הוא #$5.\nאנא ציינו את כל הפרטים הללו בכל פנייה למפעילי המערכת.",
+       "blockedtext": "<strong>שם המשתמש או כתובת ה־IP שלך נחסמו.</strong>\n\nהחסימה בוצעה על ידי $1.\nהסיבה שניתנה לכך היא <em>$2</em>.\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\nאין באפשרותך להשתמש בתכונת \"שליחת דואר אלקטרוני למשתמש זה\" אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$5.\nיש לציין את כל הפרטים הללו בכל פנייה לבירור החסימה.",
+       "autoblockedtext": "כתובת ה־IP שלך נחסמה באופן אוטומטי כיוון שמשתמש אחר, שנחסם על־ידי $1, השתמש בה.\nהסיבה שניתנה לחסימה היא:\n\n:<em>$2</em>\n\n* תחילת החסימה: $8\n* פקיעת החסימה: $6\n* החסימה שבוצעה: $7\n\nבאפשרותך ליצור קשר עם $1 או עם כל אחד מ[[{{MediaWiki:Grouppage-sysop}}|מפעילי המערכת]] האחרים כדי לדון בחסימה.\n\nאין באפשרותך להשתמש בתכונת \"שליחת דואר אלקטרוני למשתמש זה\" אם לא ציינת כתובת דוא\"ל תקפה ב[[Special:Preferences|העדפות המשתמש שלך]] או אם נחסמת משליחת דוא\"ל.\n\nכתובת ה־IP הנוכחית שלך היא $3, ומספר החסימה שלך הוא #$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 כדי לערוך דפים.",
        "confirmedittext": "עליכם לאמת את כתובת הדוא\"ל שלכם לפני שתוכלו לערוך דפים. אנא הגדירו ואמתו את כתובת הדוא\"ל שלכם באמצעות [[Special:Preferences|העדפות המשתמש]] שלכם.",
        "pageinfo-length": "אורך הדף (בבייטים)",
        "pageinfo-article-id": "מזהה הדף",
        "pageinfo-language": "שפת התוכן של הדף",
+       "pageinfo-language-change": "שינוי",
        "pageinfo-content-model": "מודל התוכן של הדף",
        "pageinfo-content-model-change": "שינוי",
        "pageinfo-robot-policy": "איסוף על־ידי רובוטים של מנועי חיפוש",
        "log-show-hide-patrol": "$1 יומן שינויים בדוקים",
        "log-show-hide-tag": "$1 יומן תגיות",
        "confirm-markpatrolled-button": "אישור",
-       "confirm-markpatrolled-top": "×\9cס×\9e×\9f ×\90ת ×\92רס×\94 $3 ×©×\9c $2 כבדוקה?",
+       "confirm-markpatrolled-top": "×\9cס×\9e×\9f ×\90ת ×\92רס×\94 $3 ×\91×\93×£ $2 כבדוקה?",
        "deletedrevision": "מחיקת גרסה ישנה ($1)",
        "filedeleteerror-short": "שגיאה במחיקת הקובץ: $1",
        "filedeleteerror-long": "שגיאות שאירעו בעת מחיקת הקובץ:\n\n$1",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|העביר|העבירה}} את הדף $3 לשם $4 בלי להשאיר הפניה",
        "logentry-move-move_redir": "$1 {{GENDER:$2|העביר|העבירה}} את הדף $3 לשם $4 תוך דריסת הפניה",
        "logentry-move-move_redir-noredirect": "$1 {{GENDER:$2|העביר|העבירה}} את הדף $3 לשם $4 תוך דריסת הפניה ובלי להשאיר הפניה",
-       "logentry-patrol-patrol": "$1 {{GENDER:$2|ס×\99×\9e×\9f|ס×\99×\9e× ×\94}} ×\90ת ×\94×\92רס×\94 $4 ×\91×\93×£ $3 ×\9b×\91×\93×\95ק×\94",
-       "logentry-patrol-patrol-auto": "$1 {{GENDER:$2|ס×\99×\9e×\9f|ס×\99×\9e× ×\94}} ×\90×\95×\98×\95×\9e×\98×\99ת ×\90ת ×\94×\92רס×\94 $4 ×\91×\93×£ $3 ×\9b×\91×\93×\95ק×\94",
+       "logentry-patrol-patrol": "$1 {{GENDER:$2|סימן|סימנה}} את גרסה $4 בדף $3 כבדוקה",
+       "logentry-patrol-patrol-auto": "$1 {{GENDER:$2|סימן|סימנה}} אוטומטית את גרסה $4 בדף $3 כבדוקה",
        "logentry-newusers-newusers": "חשבון המשתמש $1 {{GENDER:$2|נוצר}}",
        "logentry-newusers-create": "חשבון המשתמש $1 {{GENDER:$2|נוצר}}",
        "logentry-newusers-create2": "חשבון המשתמש $3 נוצר על־ידי $1",
index 753316c..97f2dea 100644 (file)
@@ -74,7 +74,8 @@
                        "Upendradutt93",
                        "Nemo bis",
                        "Wassan.anmol",
-                       "Ziyaurr"
+                       "Ziyaurr",
+                       "NehalDaveND"
                ]
        },
        "tog-underline": "कड़ियाँ अधोरेखन:",
        "viewsourcetext": "आप इस पृष्ठ का स्रोत देख सकते हैं और उसकी नकल उतार सकते हैं:",
        "viewyourtext": "आप इस पृष्ठ में ''अपने सम्पादन'' का स्रोत देख सकते हैं और उसकी नकल उतार सकते हैं:",
        "protectedinterface": "यह पृष्ठ इस विकी के सॉफ़्टवेयर का इंटरफ़ेस पाठ देता है, और इसे गलत प्रयोग से बचाने के लिये सुरक्षित कर दिया गया है।\nसभी विकियों के लिए अनुवाद जोड़ने या बदलने के लिए कृपया मीडियाविकि के क्षेत्रीयकरण प्रकल्प [https://translatewiki.net/ translatewiki.net] का प्रयोग करें।",
-       "editinginterface": "<strong>à¤\9aà¥\87तावनà¥\80:</strong> à¤\86प à¤\8fà¤\95 à¤\90सà¥\87 à¤ªà¥\83षà¥\8dठ à¤\95à¥\8b à¤¬à¤¦à¤² à¤°à¤¹à¥\87 à¤¹à¥\88à¤\82 à¤\9cà¥\8b à¤¸à¥\89फ़à¥\8dà¤\9fवà¥\87यर à¤\95ा à¤\87à¤\82à¤\9fरफ़à¥\87स à¤ªà¤¾à¤  à¤ªà¥\8dरदान à¤\95रता à¤¹à¥\88।\nà¤\87स à¤ªà¥\83षà¥\8dठ à¤\95à¥\8b à¤¬à¤¦à¤²à¤¨à¥\87 à¤¸à¥\87 à¤\85नà¥\8dय à¤¸à¤¦à¤¸à¥\8dयà¥\8bà¤\82 à¤\95à¥\8b à¤ªà¥\8dरदरà¥\8dशित à¤\87à¤\82à¤\9fरफ़à¥\87स à¤\95à¥\80 à¤¶à¤\95à¥\8dलà¥\8bसà¥\82रत में बदलाव आएगा।",
+       "editinginterface": "<strong>à¤\9aà¥\87तावनà¥\80:</strong> à¤\86प à¤\8fà¤\95 à¤\90सà¥\87 à¤ªà¥\83षà¥\8dठ à¤\95à¥\8b à¤¬à¤¦à¤² à¤°à¤¹à¥\87 à¤¹à¥\88à¤\82 à¤\9cà¥\8b à¤¸à¥\89फ़à¥\8dà¤\9fवà¥\87यर à¤\95ा à¤\87à¤\82à¤\9fरफ़à¥\87स à¤ªà¤¾à¤  à¤ªà¥\8dरदान à¤\95रता à¤¹à¥\88।\nà¤\87स à¤ªà¥\83षà¥\8dठ à¤\95à¥\8b à¤¬à¤¦à¤²à¤¨à¥\87 à¤¸à¥\87 à¤\85नà¥\8dय à¤¸à¤¦à¤¸à¥\8dयà¥\8bà¤\82 à¤\95à¥\8b à¤ªà¥\8dरदरà¥\8dशित à¤\87à¤\82à¤\9fरफ़à¥\87स à¤\95à¥\80 à¤¸à¥\8dवरà¥\82प में बदलाव आएगा।",
        "translateinterface": "सभी विकियों के लिए अनुवाद जोड़ने या बदलने के लिए मीडियाविकि क्षेत्रीयकरण परियोजना [https://translatewiki.net/ translatewiki.net] का प्रयोग करें।",
        "cascadeprotected": "यह पृष्ठ सुरक्षित हैं, क्योंकि यह निम्नलिखित {{PLURAL:$1|पृष्ठ|पृष्ठों}} की सुरक्षा-सीढ़ी में समाविष्ट है:\n$2",
        "namespaceprotected": "आपको '''$1''' नामस्थान में समाविष्ट पृष्ठों को बदलने की अनुमति नहीं है।",
        "prefs-changeemail": "ई-मेल पता परिवर्तित करें",
        "prefs-setemail": "ई-मेल पता सेट करें",
        "prefs-email": "ई-मेल वरीयताएँ",
-       "prefs-rendering": "शà¤\95à¥\8dलà¥\8bसà¥\82रत",
+       "prefs-rendering": "सà¥\8dवरà¥\82प",
        "saveprefs": "संजोएँ",
        "restoreprefs": "वापिस मूल जमावों पर आ जाएँ (सभी भागों में)",
        "prefs-editing": "संपादन",
        "log-action-filter-newusers-create2": "पंजीकृत सदस्य द्वारा निर्मित",
        "log-action-filter-newusers-autocreate": "स्वतः निर्मित",
        "log-action-filter-newusers-byemail": "पासवर्ड ईमेल द्वारा भेजा गया के साथ निर्मित",
-       "log-action-filter-patrol-patrol": "à¤\85पनà¥\87 à¤¸à¥\87 à¤ªà¤°à¥\80à¤\95à¥\8dषण",
+       "log-action-filter-patrol-patrol": "सदसà¥\8dय à¤¦à¥\8dवारा à¤ªà¤°à¥\80à¤\95à¥\8dषित",
        "log-action-filter-patrol-autopatrol": "स्वतः पुनरीक्षण",
        "log-action-filter-protect-protect": "सुरक्षा",
        "log-action-filter-protect-modify": "सुरक्षा परिवर्तन",
index b260665..fb43875 100644 (file)
        "searchprofile-advanced-tooltip": "Traži u zadanom imenskom prostoru",
        "search-result-size": "$1 ({{PLURAL:$2|1 riječ|$2 riječi}})",
        "search-result-category-size": "{{PLURAL:$1|1 član|$1 člana|$1 članova}} ({{PLURAL:$2|1 potkategorija|$2 potkategorije|$2 potkategorija}}, {{PLURAL:$3|1 datoteka|$3 datoteke|$3 datoteka}})",
-       "search-redirect": "(preusmjeravanje $1)",
+       "search-redirect": "(preusmjeravanje $1)",
        "search-section": "(odlomak $1)",
        "search-category": "(kategorija $1)",
        "search-suggest": "Mislili ste: $1",
        "prefs-watchlist-edits-max": "Maksimalni broj: 1000",
        "prefs-watchlist-token": "Token popisa praćenja:",
        "prefs-misc": "Razno",
-       "prefs-resetpass": "Promijeni zaporku",
+       "prefs-resetpass": "promijeni zaporku",
        "prefs-changeemail": "promijeni adresu e-pošte",
        "prefs-setemail": "Postavite E-mail adresu",
        "prefs-email": "Mogućnosti e-maila",
        "prefs-advancedrendering": "Napredne mogućnosti",
        "prefs-advancedsearchoptions": "Napredne mogućnosti",
        "prefs-advancedwatchlist": "Napredne mogućnosti",
-       "prefs-displayrc": "Prikaži opcije",
+       "prefs-displayrc": "Mogućnosti prikaza",
        "prefs-displaywatchlist": "Mogućnosti prikaza",
        "prefs-diffs": "Razlike između inačica uređivanja",
        "prefs-help-prefershttps": "Ova mogućnost će stupiti na snagu kod sljedeće prijave.",
        "prefswarning-warning": "Napravili ste promjene u Vašim postavkama koje još nisu snimljene.\nAko napustite ovu stranicu bez pritiska na \"$1\", postavke neće biti ažurirane.",
        "prefs-tabs-navigation-hint": "Savjet: možete rabiti tipke sa strjelicama lijevo i desno za prebacivanje između kartica na popisu kartica.",
        "userrights": "Upravljanje suradničkim pravima",
-       "userrights-lookup-user": "Upravljaj suradničkim skupinama",
+       "userrights-lookup-user": "Izaberi suradnika",
        "userrights-user-editname": "Unesite suradničko ime:",
-       "editusergroup": "Uredi suradničke skupine",
+       "editusergroup": "Učitaj suradničke skupine",
        "editinguser": "Promjena suradničkih prava za suradnika '''[[User:$1|$1]]''' $2",
        "userrights-editusergroup": "Uredi suradničke skupine",
        "saveusergroups": "Snimi suradničke skupine",
        "tooltip-ca-move": "Premjesti ovu stranicu",
        "tooltip-ca-watch": "Dodaj ovu stranicu na svoj popis praćenja",
        "tooltip-ca-unwatch": "Ukloni ovu stranicu s popisa praćenja",
-       "tooltip-search": "Pretraži {{SITENAME}}",
+       "tooltip-search": "Pretraži projekt {{SITENAME}}",
        "tooltip-search-go": "Idi na stranicu s ovim imenom ako ona postoji",
        "tooltip-search-fulltext": "Traži ovaj tekst na svim stranicama",
        "tooltip-p-logo": "Posjeti glavnu stranicu",
        "tag-filter": "Filtar [[Special:Tags|oznaka]]:",
        "tag-filter-submit": "Filtar",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Oznaka|Oznake}}]]: $2)",
+       "tag-mw-contentmodelchange": "promjena modela sadržaja",
+       "tag-mw-contentmodelchange-description": "Uređivanja koja [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel mijenjanju model sadržaja] stranice",
        "tags-title": "Oznake",
        "tags-intro": "Ova je stranica popis oznaka s kojima softver može označiti promjenu te njihovo značenje.",
        "tags-tag": "Naziv oznake",
        "feedback-termsofuse": "Slažem se da povratne informacije objavljujem u skladu s Uvjetima uporabe.",
        "feedback-thanks": "Hvala! Vaš odgovor je snimljen na stranicu \"[$2 $1]\".",
        "feedback-thanks-title": "Hvala!",
-       "searchsuggest-search": "Traži",
+       "searchsuggest-search": "Pretraži projekt {{SITENAME}}",
        "searchsuggest-containing": "sadrži....",
        "api-error-badaccess-groups": "Nemate ovlasti za postavljanje datoteka na ovu wiki.",
        "api-error-badtoken": "Interna pogrješka: Token nije ispravan.",
index 9735a24..6b1e806 100644 (file)
        "watchlisttools-raw": "Խմբագրել հում հսկացանկը",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|քննարկում]])",
        "version": "ՄեդիաՎիքի տարբերակը",
-       "version-ext-license": "Ô¼Õ«Ö\81Õ¥Õ¶Õ¦Õ«Õ¡",
+       "version-ext-license": "Ô±Ö\80Õ¿Õ¸Õ¶Õ¡Õ£Õ«Ö\80",
        "version-ext-colheader-name": "Ընդլայնում",
        "version-ext-colheader-version": "Տարբերակ",
-       "version-ext-colheader-license": "Ô¼Õ«Ö\81Õ¥Õ¶Õ¦Õ«Õ¡",
-       "version-license-title": "Ô¼Õ«Ö\81Õ¥Õ¶Õ¦Õ«Õ¡ $1-ի համար",
+       "version-ext-colheader-license": "Ô±Ö\80Õ¿Õ¸Õ¶Õ¡Õ£Õ«Ö\80",
+       "version-license-title": "Ô±Ö\80Õ¿Õ¸Õ¶Õ¡Õ£Õ«Ö\80 $1-ի համար",
        "version-poweredby-credits": "Այս վիքին աշխատում է '''[https://www.mediawiki.org/ MediaWiki]'''֊ով, copyright © 2001-$1 $2։",
        "fileduplicatesearch": "Փնտրել կրկնօրինակ պատկերներ",
        "fileduplicatesearch-summary": "Փնտրել կրկնօրինակ պատկերներ՝ հեշ արժեքների հիման վրա",
index face238..6eed285 100644 (file)
        "blockedtitle": "Le usator es blocate",
        "blockedtext": "'''Tu nomine de usator o adresse IP ha essite blocate.'''\n\nLe blocada esseva facite per $1.\nLe motivo presentate es ''$2''.\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Le blocato intendite: $7\n\nTu pote contactar $1 o un altere [[{{MediaWiki:Grouppage-sysop}}|administrator]] pro discuter le blocada.\nTu non pote usar le function 'inviar e-mail a iste usator' salvo que un adresse de e-mail valide es specificate in le\n[[Special:Preferences|preferentias de tu conto]] e que tu non ha essite blocate de usar lo.\nTu adresse IP actual es $3, e le ID del blocada es #$5.\nPer favor include tote le detalios supra specificate in omne correspondentia.",
        "autoblockedtext": "Tu adresse de IP ha essite automaticamente blocate proque un altere usator lo usava qui esseva blocate per $1.\nLe motivo presentate es:\n\n:''$2''\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Blocato intendite: $7\n\nTu pote contactar $1 o un del altere [[{{MediaWiki:Grouppage-sysop}}|administratores]] pro discuter le blocada.\n\nNota que tu non pote utilisar le function \"inviar e-mail a iste usator\" salvo que tu ha registrate un adresse de e-mail valide in tu [[Special:Preferences|preferentias de usator]] e que tu non ha essite blocate de usar lo.\n\nTu adresse IP actual es $3, e le ID del blocada es #$5.\nPer favor include tote le detalios supra specificate in omne correspondentia.",
+       "systemblockedtext": "Tu nomine de usator o adresse IP ha essite blocate automaticamente per MediaWiki.\nLe motivo presentate es:\n\n:<em>$2</em>\n\n* Initio del blocada: $8\n* Expiration del blocada: $6\n* Blocato intendite: $7\n\nTu adresse IP actual es $3.\nPer favor, include tote le detalios enumerate hic supra in omne questiones que tu pone.",
        "blockednoreason": "nulle motivo specificate",
        "whitelistedittext": "Tu debe $1 pro poter modificar paginas.",
        "confirmedittext": "Tu debe confirmar tu adresse de e-mail pro poter modificar paginas.\nPer favor entra e valida tu adresse de e-mail per medio de tu [[Special:Preferences|preferentias de usator]].",
        "emailccsubject": "Copia de tu message a $1: $2",
        "emailsent": "E-mail inviate",
        "emailsenttext": "Tu message de e-mail ha essite inviate.",
-       "emailuserfooter": "Iste e-mail ha essite {{GENDER:$1|inviate}} per $1 a {{GENDER:$2|$2}} con le function \"{{int:emailuser}}\" in {{SITENAME}}.",
+       "emailuserfooter": "Iste e-mail ha essite {{GENDER:$1|inviate}} per $1 a {{GENDER:$2|$2}} con le function \"{{int:emailuser}}\" in {{SITENAME}}.\n{{GENDER:$2|Le}} message ha essite inviate directemente al {{GENDER:$1|expeditor|expeditrice}} original, revelante {{GENDER:$2|tu}} adresse de e-mail a {{GENDER:$1|ille|illa}}.",
        "usermessage-summary": "Lassante un message de systema.",
        "usermessage-editor": "Messagero del systema",
        "watchlist": "Observatorio",
        "pageinfo-length": "Dimension del pagina (in bytes)",
        "pageinfo-article-id": "ID del pagina",
        "pageinfo-language": "Lingua del contento del pagina",
+       "pageinfo-language-change": "cambiar",
        "pageinfo-content-model": "Modello de contento de pagina",
        "pageinfo-content-model-change": "cambiar",
        "pageinfo-robot-policy": "Indexation per robots",
        "restrictionsfield-badip": "Adresse o intervallo IP non valide: $1",
        "restrictionsfield-label": "Intervallos IP permittite:",
        "restrictionsfield-help": "Un adresse IP o intervallo CIDR per linea. Pro activar toto, usa<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "version $1",
        "pageid": "ID de pagina $1"
 }
index 998280b..45be55c 100644 (file)
        "blockedtitle": "Pengguna diblokir",
        "blockedtext": "'''Nama pengguna atau alamat IP Anda telah diblokir.'''\n\nBlokir dilakukan oleh $1.\nAlasan yang diberikan adalah ''$2''.\n\n* Diblokir sejak: $8\n* Blokir kedaluwarsa pada: $6\n* Sasaran pemblokiran: $7\n\nAnda dapat menghubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|pengurus lainnya]] untuk membicarakan hal ini.\n\nAnda tidak dapat menggunakan fitur 'Kirim surel ke pengguna ini' kecuali Anda telah memasukkan alamat surel yang sah di [[Special:Preferences|preferensi akun]] dan Anda tidak diblokir untuk menggunakannya.\n\nAlamat IP Anda adalah $3, dan ID pemblokiran adalah $5.\nTolong sertakan salah satu atau kedua informasi ini pada setiap pertanyaan yang Anda buat.",
        "autoblockedtext": "Alamat IP Anda telah terblokir secara otomatis karena digunakan oleh pengguna lain, yang diblokir oleh $1. Pemblokiran dilakukan atas alasan:\n\n:''$2''\n\n* Diblokir sejak: $8\n* Blokir kedaluwarsa pada: $6\n* Sasaran pemblokiran: $7\n\nAnda dapat menghubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|pengurus lainnya]] untuk membicarakan hal ini.\n\nAnda tidak dapat menggunakan fitur \"kirim surel ke pengguna ini\" kecuali Anda telah memasukkan alamat surel yang sah di [[Special:Preferences|preferensi akun]] Anda dan Anda tidak diblokir untuk menggunakannya.\n\nAlamat IP Anda saat ini adalah $3, dan ID pemblokiran adalah #$5.\nTolong sertakan informasi-informasi ini dalam setiap pertanyaan Anda.",
+       "systemblockedtext": "Nama pengguna atau alamat IP Anda telah diblokir secara otomatis oleh MediaWiki.\nAlasan yang diberikan adalah:\n\n:<em>$2</em>\n\n* Diblokir sejak: $8\n* Blokir kedaluwarsa pada: $6\n* Sasaran pemblokiran: $7\n\nAlamat IP Anda saat ini adalah $3\nMohon sertakan semua perincian di atas dalam setiap pertanyaan yang Anda ajukan.",
        "blockednoreason": "tidak ada alasan yang diberikan",
        "whitelistedittext": "Anda harus $1 untuk dapat menyunting halaman.",
        "confirmedittext": "Anda harus mengkonfirmasikan dulu alamat surel Anda sebelum menyunting halaman.\nHarap masukkan dan validasikan alamat surel Anda melalui [[Special:Preferences|halaman preferensi pengguna]] Anda.",
        "content-json-empty-object": "Objek kosong",
        "content-json-empty-array": "Larik kosong",
        "deprecated-self-close-category": "Halaman yang menggunakan tag HTML tertutup-sendiri tidak sah",
+       "deprecated-self-close-category-desc": "Halaman ini mengandung tag HTML tertutup-sendiri yang tidak sah, seperti <code>&lt;b/></code> atau <code>&lt;span/></code>.  Perilaku tag seperti ini akan segera berubah agar konsisten dengan spesifikasi HTML5, jadi penggunaannya dalam teks wiki tidak lagi disarankan.",
        "duplicate-args-warning": "<strong>Peringatan:</strong> [[:$1]] memanggil [[:$2]] dengan nilai lebih dari satu untuk parameter \"$3\". Hanya nilai terakhir yang tersedia yang akan digunakan.",
        "duplicate-args-category": "Halaman dengan argumen ganda di pemanggilan templat",
        "duplicate-args-category-desc": "Halaman ini berisi pemanggilan templat yang menggunakan argumen ganda, seperti <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> atau <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "file-thumbnail-no": "Nama berkas dimulai dengan <strong>$1</strong>.\nTampaknya berkas ini merupakan gambar dengan ukuran diperkecil ''(miniatur)''.\nJika Anda memiliki versi resolusi penuh dari gambar ini, harap muatkan berkas tersebut. Jika tidak, harap ubah nama berkas ini.",
        "fileexists-forbidden": "Suatu berkas dengan nama ini telah ada dan tak dapat ditimpa.\nJika Anda masih ingin memuat berkas Anda, silakan kembali dan gunakan nama baru. [[File:$1|thumb|center|$1]]",
        "fileexists-shared-forbidden": "Ditemukan berkas lain dengan nama yang sama di repositori bersama.\nJika Anda tetap ingin memuatkan berkas Anda, harap kembali dan gunakan nama lain. [[File:$1|thumb|center|$1]]",
+       "fileexists-no-change": "Unggahan ini adalah salinan persis versi saat ini dari <strong>[[:$1]]</strong>.",
+       "fileexists-duplicate-version": "Unggahan ini adalah salinan persis {{PLURAL:$2|versi terdahulu version|beberapa versi terdahulu}} dari <strong>[[:$1]]</strong>.",
        "file-exists-duplicate": "Berkas ini berduplikasi dengan {{PLURAL:$1|berkas|berkas-berkas}} berikut:",
        "file-deleted-duplicate": "Sebuah berkas yang identik dengan berkas ini ([[:$1]]) sudah pernah dihapuskan sebelumnya. Anda harus memeriksa sejarah penghapusan berkas tersebut sebelum melanjutkan memuat ulang berkas ini.",
        "file-deleted-duplicate-notitle": "Sebuah berkas yang identik dengan berkas ini sebelumnya telah dihapus, dan judul yang digunakan telah ditahan.\nAnda harus meminta bantuan seseorang dengan kemampuan untuk melihat data berkas yang ditahan untuk meninjau situasi sebelum anda mengunggah kembali.",
        "pageinfo-length": "Panjang halaman (dalam bita)",
        "pageinfo-article-id": "ID Halaman",
        "pageinfo-language": "Bahasa isi halaman",
+       "pageinfo-language-change": "ubah",
        "pageinfo-content-model": "Model isi halaman",
        "pageinfo-content-model-change": "ubah",
        "pageinfo-robot-policy": "Pengindeksan oleh robot",
        "htmlform-time-placeholder": "JJ:MM:DD",
        "htmlform-datetime-placeholder": "TTTT-BB-HH JJ:MM:DD",
        "htmlform-date-invalid": "Nilai yang diberikan tidak dikenali sebagai tanggal. Coba lagi menggunakan format TTTT-BB-HH.",
+       "htmlform-datetime-invalid": "Nilai yang Anda masukkan tidak dikenali sebagai tanggal dan waktu. Coba gunakan format YYYY-MM-DD HH:MM:SS",
+       "htmlform-date-toolow": "Nilai yang Anda masukkan adalah sebelum tanggal paling dini yang dibolehkan $1",
+       "htmlform-date-toohigh": "Nilai yang Anda masukkan adalah setelah tanggal paling akhir  yang dibolehkan $1",
+       "htmlform-time-toolow": "Nilai yang Anda tentukan adalah sebelum waktu paling dini yang dibolehkan $1",
+       "htmlform-time-toohigh": "Nilai yang Anda tentukan adalah setelah waktu paling baru yang dibolehkan $1",
        "htmlform-title-badnamespace": "[[:$1]] tidak berada dalam ruang nama \"{{ns:$2}}\".",
        "htmlform-title-not-creatable": "\"$1\" bukan merupakan judul halaman yang dapat dibuat",
        "htmlform-title-not-exists": "$1 tidak ada.",
        "linkaccounts-submit": "Tautkan akun",
        "unlinkaccounts": "Lepastautkan akun",
        "unlinkaccounts-success": "Akun berikut telah dilepastautkan.",
+       "userjsispublic": "Harap perhatikan: subhalaman Javascript sebaiknya tidak mengandung data rahasia, karena dapat dilihat oleh pengguna lain.",
+       "usercssispublic": "Harap perhatikan: subhalaman CSS sebaiknya tidak mengandung data rahasia karena dapat dilihat oleh pengguna lain.",
        "restrictionsfield-badip": "Alamat IP atau rentang IP tidak sah: $1",
        "restrictionsfield-label": "Rentang IP yang diizinkan:",
        "restrictionsfield-help": "Satu alamat IP atau rentang CIDR per baris. Untuk mengaktifkan semuanya, gunakan <br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "revisi $1",
        "pageid": "ID halaman $1"
 }
index dd6c345..604ff49 100644 (file)
        "userrights-user-editname": "Inserire il nome utente:",
        "editusergroup": "Modifica gruppi utente",
        "editinguser": "Modifica in corso dei diritti dell'{{GENDER:$1|utente}} <strong>[[User:$1|$1]]</strong> $2",
+       "viewinguserrights": "Visualizzazione dei diritti dell'{{GENDER:$1|utente}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Modifica gruppi utente",
        "userrights-viewusergroup": "Visualizza gruppi utente",
        "saveusergroups": "Salva gruppi {{GENDER:$1|utente}}",
        "action-writeapi": "usare le API in scrittura",
        "action-delete": "cancellare questa pagina",
        "action-deleterevision": "cancellare versioni",
+       "action-deletelogentry": "cancellare le voci di registro",
        "action-deletedhistory": "visualizzare la cronologia cancellata di una pagina",
+       "action-deletedtext": "visualizzare il testo delle versioni cancellate",
        "action-browsearchive": "cercare pagine cancellate",
        "action-undelete": "recuperare pagine",
        "action-suppressrevision": "rivedere e ripristinare le versioni nascoste",
        "action-userrights-interwiki": "modificare i diritti degli utenti su altre wiki",
        "action-siteadmin": "bloccare e sbloccare il database",
        "action-sendemail": "inviare email",
+       "action-editmyoptions": "modificare le proprie preferenze",
        "action-editmywatchlist": "modificare i propri osservati speciali",
        "action-viewmywatchlist": "vedere i propri osservati speciali",
        "action-viewmyprivateinfo": "vedere i propri dati personali",
        "usercssispublic": "Ricorda: le sottopagine CSS non devono contenere dati riservati poichè sono visualizzabili da altri utenti.",
        "restrictionsfield-badip": "Indirizzo IP o intervallo non valido: $1",
        "restrictionsfield-label": "Intervalli IP consentiti:",
-       "restrictionsfield-help": "Un indirizzo IP o intervallo CIDR per linea. Per consentire tutto, utilizza<br><code>0.0.0.0/0</code><br><code>::/0</code>"
+       "restrictionsfield-help": "Un indirizzo IP o intervallo CIDR per linea. Per consentire tutto, utilizza<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "versione $1",
+       "pageid": "ID della pagina $1"
 }
index 2f0a69b..bd26006 100644 (file)
        "protectedinterface": "Kaca iki isiné tèks antarmuka sing dienggo software lan wis dikunci kanggo menghindari kasalahan.",
        "editinginterface": "'''Pènget:''' Panjenengan nyunting kaca sing dianggo nyedyakaké tèks antarmuka kanggo piranti alus.\nPangowahan kaca iki bakal awèh pangaruh marang tampilan antarmuka panganggo kanggoné panganggo liya.\nKanggo terjemahan, mangga nganggo [https://translatewiki.net/wiki/Main_Page?setlang=en translatewiki.net], proyèk lokalisasi MediaWiki.",
        "translateinterface": "Saperlu nambah utawa ngowah pertalan tumrap kabèh wiki, mangga anggoa [https://translatewiki.net/ translatewiki.net] minangka proyèk panglokaling MediaWiki.",
-       "cascadeprotected": "Kaca iki wis direksa saka panyuntingan amerga disertakaké ing {{PLURAL:$1|kaca|kaca-kaca}} ngisor iki sing wis direksa mawa opsi \"runtun\" diaktifaké:\n$2",
+       "cascadeprotected": "Kaca iki wis direksa saka besutan amarga katransklusi ing {{PLURAL:$1|kaca, sing|kaca-kaca, sing}} kareksa mawa pilihan \"runut\" murub:\n$2",
        "namespaceprotected": "Panjenengan ora kagungan idin kanggo nyunting kaca ing bilik nama '''$1'''.",
        "customcssprotected": "Sampéyan ora dililakaké nyunting kaca CSS iki amarga kaisi pangaturan pribadi saka panganggo liya.",
        "customjsprotected": "Sampéyan ora dililakaké nyunting kaca JavaScript iki amarga kaisi pangaturan pribadi saka panganggo liya.",
        "passwordremindertext": "Ana wong (mbokmanawa panjenengan dhéwé, saka alamat IP $1) nyuwun supaya dikirimi tembung sandhi anyar kanggo {{SITENAME}} ($4). Tembung sandi sawetara kanggo panganggo \"$2\" wis digawé lan saiki \"$3\". Yèn panjenengan pancèn nggayuh iki, mangga énggal mlebu log lan ngganti tembung sandi saiki.\nTembung sandi sawetara mau bakal kadaluwarsa ing {{PLURAL:$5|sadina|$5 dina}}.\nYèn wong liya sing nglakoni panyuwunan iki, utawa panjenengan éling tembung sandi panjenengan, lan ora kepéngin ngowahi, panjenengan ora usah nggubris pesen iki lan bisa tetep nganggo tembung sandi lawas.",
        "noemail": "Ora ana alamat layang e-mail sing kacathet kanggo panganggo \"$1\".",
        "noemailcreate": "Panjenengan kudu maringi alamat e-mail sing absah",
-       "passwordsent": "Tembung sandhi anyar wis dikirim menyang alamat layang e-mail panjenengan sing wis didaftar kanggo \"$1\". Mangga mlebu log manèh sawisé nampa e-mail iku.",
+       "passwordsent": "Tembung sandi anyar wis dikirim menyang alamat layang èlèktronik tumrap \"$1\". \nMangga mlebu log manèh sawisé panjenengan nampa iku.",
        "blocked-mailpassword": "Alamat IP panjenengan diblokir saka panyuntingan, mulané panjenengan ora olèh nganggo fungsi pèngetan tembung sandhi kanggo ''mencegah penyalahgunaan''.",
        "eauthentsent": "Sawijining layang élèktronik (e-mail) kanggo ndhedhes (konfirmasi) wis dikirim menyang alamat layang élèktronik sampeyan. \n\nSadhurunge layang élèktronik liyane dikirim menyang akun kuwi, sampeyan kudu melu parentah ing layang kuwi, kanggo mastikne yen alamat layang kuwi bener-bener dhuweke sampeyan.",
        "throttled-mailpassword": "Layang kanggo mbalèkaké tembung sandhi wis dikirim sasuwené ing {{PLURAL:$1|jam|$1 jam}}.\nKanggo nyegah ananing tumindhak culika, namung sak layang kanggo mbalèkaké tembung sandhi sing bakal dikirim sasuwéné ing {{PLURAL:$1|jam|$1 jam}}.",
        "cannotchangeemail": "Alamat layang èlèktronik akun ora bisa diganti nèng wiki iki.",
        "emaildisabled": "Situs iki ora bisa ngirim layang èlèktronik.",
        "accountcreated": "Akun wis kagawé",
-       "accountcreatedtext": "Akun panganggo [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|rembug]]) wis digawé.",
+       "accountcreatedtext": "Akun naraguna [[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|rembug]]) wis digawé.",
        "createaccount-title": "Gawé rékening kanggo {{SITENAME}}",
        "createaccount-text": "Ana wong sing nggawé sawijining akun utawa rékening kanggo alamat e-mail panjenengan ing {{SITENAME}} ($4) mawa jeneng \"$2\" lan tembung sandi \"$3\". Panjenengan disaranaké kanggo mlebu log lan ngganti tembung sandi panjenengan saiki.\n\nPanjenengan bisa nglirwakaké pesen iki yèn akun utawa rékening iki digawé déné sawijining kaluputan.",
        "login-throttled": "Panjenengan wis kakèhan njajal mlebu log.\nTulung nunggu dhisik $1 sadurungé njajal manèh.",
        "loginreqtitle": "Kudu mlebu",
        "loginreqlink": "mlebu",
        "loginreqpagetext": "Panjenengan kudu $1 kanggo bisa mirsani kaca liyané.",
-       "accmailtitle": "Tembung wadi wis kinirim",
-       "accmailtext": "Sawijining tembung sandi sembarang kanggo [[User talk:$1|$1]] wis dikirim menyang $2.\n\nTembung sandi kanggo panganggo anyar iki isa diganti ing kaca ''[[Special:ChangePassword|ganti tembung sandi]]'' sawisé mlebu log.",
+       "accmailtitle": "Tembung sandi wis kinirim",
+       "accmailtext": "Tembung sandi sembarang kanggo [[User talk:$1|$1]] wis dikirim menyang $2.\n\nTembung sandi iki bisa diganti ing kaca <em>[[Special:ChangePassword|salin tembung sandi]]</em> sawisé mlebu log.",
        "newarticle": "(Anyar)",
        "newarticletext": "Katonané panjenengan ngetutaké pranala artikel sing durung ana.\nManawa kersa manulis artikel iki, manggaa. (Mangga mirsani [$1 Pitulung] kanggo informasi sabanjuré).\nYèn ora sengaja tekan kéné, bisa ngeklik pencètan '''back''' waé ing panjlajah wèb panjenengan.",
        "anontalkpagetext": "---- ''Iki yaiku kaca dhiskusi sawijining panganggo anonim sing durung kagungan akun utawa ora nganggo akuné, dadi kita keeksa kudu nganggo alamat IP-né kanggo nepangi. Alamat IP kaya mengkéné iki bisa dienggo déning panganggo sing séjé-séjé. Yèn panjenengan pancèn panganggo anonim lan olèh komentar-komentar miring, mangga [[Special:CreateAccount|nggawé akun]] utawa [[Special:UserLogin|log mlebu]] supaya ora rancu karo panganggo anonim liyané ing mangsa ngarep.''",
        "readonlywarning": "'''PÈNGET: Basis data lagi dikunci amerga ana pangopènan, dadi saiki panjenengan ora bisa nyimpen kasil panyuntingan panjenengan. Panjenengan mbokmenawa prelu mindhahaké kasil panyuntingan panjenengan iki menyang panggonan liya kanggo disimpen bésuk.'''\n\nPangurus sing ngunci basis data mènèhi katrangan kaya mengkéné: $1",
        "protectedpagewarning": "'''PÈNGET:  Kaca iki wis dikunci dadi namung panganggo sing nduwé hak aksès pangurus baé sing bisa nyunting.'''\nEntri cathetan pungkasan disadiakake ing ngisor kanggo referensi:",
        "semiprotectedpagewarning": "'''Cathetan:''' Kaca iki lagi pinuju direksa, dadi namung panganggo kadaftar sing bisa nyunting.\nEntri cathetan pungkasan disadiakake ing ngisor kanggo referensi:",
-       "cascadeprotectedwarning": "'''PÈNGET:''' Kaca iki wis dikunci dadi namung panganggo mawa hak aksès pangurus waé sing bisa nyunting, amerga kalebu {{PLURAL:$1|kaca|kaca-kaca}} ing ngisor iki sing wis direksa mawa opsi 'pangreksan runtun' diaktifaké:",
+       "cascadeprotectedwarning": "<strong>Pènget:</strong> Kaca iki wis direksa saéngga mung naraguna kanthi hak pangurus waé sing bisa mbesut amarga kaca iki katransklusi ing {{PLURAL:$1|kaca|kaca-kaca}} sing kareksa runut ngisor iki:",
        "titleprotectedwarning": "'''Pènget: Kaca iki wis dikunci saéngga perlu [[Special:ListGroupRights|hak mligi]] kanggo gawéné.'''\nEntri cathetan pungkasan disadiakake ing ngisor kanggo referensi:",
        "templatesused": "{{PLURAL:$1|Cithakan|Cithakan}} sing dienggo ing kaca iki:",
        "templatesusedpreview": "{{PLURAL:$1|Cithakan|Cithakan-cithakan}} sing dienggo ing pratilik iki:",
        "minlength1": "Jeneng berkas paling ora minimal kudu awujud saaksara.",
        "illegalfilename": "Jeneng berkas \"$1\" ngandhut aksara sing ora diparengaké ana sajroning irah-irahan kaca. Mangga owahana jeneng berkas iku lan cobanen  diunggahaké manèh.",
        "filename-toolong": "Jeneng berkas ora olèh luwih dawa saka 240 bita.",
-       "badfilename": "Berkas wis diowahi dados \"$1\".",
+       "badfilename": "Jeneng barkas wis diowah dadi \"$1\".",
        "filetype-mime-mismatch": "Èkstènsi berkas \".$1\" ora cocok karo jinis MIME sing kadètèk saka berkas ($2).",
        "filetype-badmime": "Berkas mawa tipe MIME \"$1\" ora pareng diunggahaké.",
        "filetype-bad-ie-mime": "Ora bisa ngunggahaké berkas iki amarga Internet Explorer ndhétèksi minangka \"$1\", sing ora diidinaké lan minangka tipe berkas sing nduwèni potènsi mbebayani.",
index a2fd8c9..3a6eec5 100644 (file)
        "passwordreset-emaildisabled": "ამ ვიკიში ელ.ფოსტის ფუნქციები გამორთულია.",
        "passwordreset-username": "მომხმარებლის სახელი:",
        "passwordreset-domain": "დომენი:",
-       "passwordreset-capture": "გამოსული ელ-ფოსტის ხილვა?",
-       "passwordreset-capture-help": "თუ მონიშნავთ ამ უჯრას, მაშინ თქვენ შეგეძლებათ მომხმარებლისათვის გაგზავნილი ელ.ფოსტის ნახვა (დროებითი პაროლით).",
        "passwordreset-email": "ელ. ფოსტის მისამართი:",
        "passwordreset-emailtitle": "ანგარიშის მონაცემები {{SITENAME}}-თვის",
        "passwordreset-emailtext-ip": "ვიღაცამ (შესაძლოა თქვენ, ამ IP-მისამართიდან $1) მოითხოვა თქვენი \nპაროლის თავიდან დაყენება საიტისათვის {{SITENAME}} ($4).\n{{PLURAL:$3|შემდეგი ანგარიში მიბმულია|შემდეგი ანგარიშები მიბმულია}} ამ ელ.ფოსტის მისამართზე:\n\n$2\n\n{{PLURAL:$3|ეს დროებითი პაროლი|ეს დროებითი პაროლები}} იმოქმედებს {{PLURAL:$5|ერთი დღე|$5 დღე}}.\nთქვენ უნდა შეხვიდეთ სისტემაში და აირჩიოთ ახალი პაროლი.\nთუ თქვენ არ გაგიკეთებიათ აღნიშნული მოთხოვნა, ან გაიხსენეთ თქვენი პაროლი\nდა აღარ გსურთ მისი შეცვლა, მაშინ შეგიძლიათ იგნორირება გაუკეთოთ ამ შეტყობინებას\nდა გააგრძელოთ თქვენი ძველი პაროლის გამოყენება.",
        "passwordreset-emailelement": "მომხმარებლის სახელი: \n$1\n\nდროებითი პაროლი: \n$2",
        "passwordreset-emailsentemail": "თუ ეს მეილი თქვენს ანგარიშთანაა დაკავშირებული, გაიგზავნება პაროლის თავიდან დასაყენებელი ელექტრონული ფოსტა.",
        "passwordreset-emailsentusername": "თუ არსებობს მეილი, რომელიც ამ ანგარიშთანაა დაკავშირებული, გაიგზავნება პაროლის თავიდან დასაყენებელი ელექტრონული ფოსტა.",
-       "passwordreset-emailsent-capture2": "პაროლის გაუქმების შესახებ {{PLURAL:$1|მეილი|მეილები}} გაიგზავნა. {{PLURAL:$1|სახელი და პაროლი|სახელებისა და პაროლების სია}} არის ნაჩვენები ქვემოთ.",
-       "passwordreset-emailerror-capture2": "{{GENDER:$2|მომხმარებელთან}} მეილის გაგზავნა ვერ მოხერხდა: $1 {{PLURAL:$3|სახელი და პაროლი|სახელებისა და პაროლების სია}} არის ნაჩვენები ქვემოთ.",
        "passwordreset-nocaller": "გამომძახებელი უნდა იყოს მიწოდებული",
        "passwordreset-nosuchcaller": "გამომძახებელი არ არსებობს: $1",
        "passwordreset-ignored": "პაროლის გაუქმება არ იქნა შესრულებული. შეიძლება კონფიგურაციაში პროვაიდერი არ იყო გათვალისწინებული?",
        "userrights-reason": "შეცვლის მიზეზი:",
        "userrights-no-interwiki": "თქვენ არ გაქვთ მომხმარებლის უფლებების რედაქტირების უფლება სხვა ვიკი-ებში.",
        "userrights-nodatabase": "მონაცემთა ბაზა $1 არ არსებობს, ან არ არის ლოკალური.",
-       "userrights-nologin": "თქვენ უნდა [[Special:UserLogin|წარადგინოთ თავი სისტემისადმი]] ადმინისისტრატორის ანგარიშით იმისთვის, რომ გასცეთ მომხმარებელთა უფლებები.",
-       "userrights-notallowed": "თქვენ არ გაქვთ მომხმარებელთა უფლებების შეცვლის უფლება.",
        "userrights-changeable-col": "ჯგუფები, რომლებიც შეგიძლიათ შეცვალოთ",
        "userrights-unchangeable-col": "ჯგუფები, რომლებიც არ შეგიძლიათ შეცვალოთ",
        "userrights-irreversible-marker": "$1*",
        "userrights-conflict": "მომხმარებელთა უფლებების კონფლიქტი! გთხოვთ ხელმეორედ შეინახოთ თქვენი ცვლილებები.",
-       "userrights-removed-self": "თქვენ წაშალეთ საკუთარი უფლება. შესაბამისად, თქვენ აღარ გექნებათ ამ გვერდთან წვდომის საშუალება",
        "group": "ჯგუფი:",
        "group-user": "მომხმარებლები",
        "group-autoconfirmed": "ავტომატურად დადასტურებული მომხმარებლები",
        "right-siteadmin": "მონაცემთა ბაზის დაბლოკვა და განბლოკვა",
        "right-override-export-depth": "გვერდების ექსპორტირება, დაკავშირებული გვერდების ჩათვლით 5-მდე სიიღრმით",
        "right-sendemail": "გაგუგზავნე ელექტრონული ფოსტა სხვა მომხმარებლებს",
-       "right-passwordreset": "ელ.ფოსტის ნახვა პაროლის შეცვლით",
        "right-managechangetags": "[[Special:Tags|ტეგების]] შექმნა და (დე)აქტივაცია",
        "right-applychangetags": "[[Special:Tags|tags]] მიღება თქვენ ცვლილებებთან ერთად",
        "right-changetags": "თვითნებური [[Special:Tags|tags]] დამატება ან წაშლა ცალკეულ ცვლილებებსა და ჟურნალის ჩანაწერებში",
        "listfiles_date": "თარიღი",
        "listfiles_name": "სახელი",
        "listfiles_user": "მომხმარებელი",
-       "listfiles_size": "ზომა (ბაიტები)",
+       "listfiles_size": "ზომა",
        "listfiles_description": "აღწერილობა",
        "listfiles_count": "ვერსიები",
        "listfiles-show-all": "სურათების ძველი ვერსიების ჩართვა",
        "protect-expiry-options": "1 საათი:1 hour,1 დღე:1 day,1 კვირა:1 week,2 კვირა:2 weeks,1 თვე:1 month,3 თვე:3 months,6 თვე:6 months,1 წელი:1 year,განუსაზღვრელი ვადით:infinite",
        "restriction-type": "უფლება",
        "restriction-level": "შეზღუდვის დონე:",
-       "minimum-size": "მინ ზომა",
+       "minimum-size": "მინ. ზომა",
        "maximum-size": "მაქს. ზომა",
        "pagesize": "(ბაიტი)",
        "restriction-edit": "რედაქტირება",
        "htmlform-user-not-exists": "<strong>$1</strong> არ არსებობს.",
        "htmlform-user-not-valid": "<strong>$1</strong> არ არის სწორი მომხმარებლის სახელი.",
        "logentry-delete-delete": "მომხმარებელმა $1 {{GENDER:$2|წაშალა}} გვერდი: „$3“",
+       "logentry-delete-delete_redir": "მომხმარებელმა $1 {{GENDER:$2|წაშალა}} გადამისამართება $3 გადაწერით",
        "logentry-delete-restore": "მომხმარებელმა $1 {{GENDER:$2|აღადგინა}} გვერდი $3",
        "logentry-delete-event": "მომხმარებელმა $1 {{GENDER:$2|შეცვალა}} {{PLURAL:$5|ჟურნალის ჩანაწერის|$5 ჟურნალის ჩანაწერების}} ხილვადობა $3-ზე: $4",
        "logentry-delete-revision": "მომხმარებელმა $1 {{GENDER:$2|შეცვალა}} {{PLURAL:$5|$5 ვერსიის|$5 ვერსიის}} ხილვადობა გვერდისათვის $3: $4",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-symbols": "სიმბოლოები",
        "special-characters-group-greek": "ბერძნული",
+       "special-characters-group-greekextended": "ბერძნული გაფართოებული",
        "special-characters-group-cyrillic": "კირილიცა",
        "special-characters-group-arabic": "არაბული",
        "special-characters-group-arabicextended": "არაბული გაფართოება",
        "mw-widgets-dateinput-no-date": "თარიღი არ არის არჩეული",
        "mw-widgets-dateinput-placeholder-day": "წწწწ-თთ-დდ",
        "mw-widgets-dateinput-placeholder-month": "წწწწ-თთ",
+       "mw-widgets-mediasearch-noresults": "შედეგები ვერ მოიძებნა.",
        "mw-widgets-titleinput-description-new-page": "გვერდი ჯერ არ არსებობს",
        "mw-widgets-titleinput-description-redirect": "გადამისამართება $1-ზე",
        "sessionmanager-tie": "შეუძლებელია მრავალი მოთხოვნის ავთენთიფიკაციის ტიპების გაერთიანება: $1.",
index 8dc9246..49993f8 100644 (file)
        "eauthentsent": "입력한 이메일로 확인 이메일을 보냈습니다.\n다른 모든 형태의 이메일을 당신의 계정으로 보내기 전에, 계정이 정말 당신의 것인지 확인하기 위해 이메일 내용의 지시대로 계정 확인 절차를 실행해 주셔야 합니다.",
        "throttled-mailpassword": "비밀번호 재설정 이메일을 이미 최근 {{PLURAL:$1|$1시간}} 안에 보냈습니다.\n악용을 방지하기 위해 비밀번호 재설정 메일은 {{PLURAL:$1|$1시간}}마다 오직 하나씩만 보낼 수 있습니다.",
        "mailerror": "메일을 보내는 중 오류: $1",
-       "acct_creation_throttle_hit": "당신의 IP 주소를 이용한 방문자가 이전에 이미 {{PLURAL:$1|계정 $1개}}를 만들어, 계정 만들기 한도를 초과하였습니다.\n따라서 지금은 이 IP 주소로는 더 이상 계정을 만들 수 없습니다.",
+       "acct_creation_throttle_hit": "당신의 IP 주소를 이용한 방문자가 $2에 이미 {{PLURAL:$1|계정 $1개}}를 만들어, 계정 만들기 한도를 초과하였습니다.\n따라서 지금은 이 IP 주소로는 더 이상 계정을 만들 수 없습니다.",
        "emailauthenticated": "이메일 주소가 $2 $3에 인증되었습니다.",
        "emailnotauthenticated": "이메일 주소를 인증하지 않았습니다.\n이메일 확인 절차를 거치지 않으면 다음 이메일 기능을 사용할 수 없습니다.",
        "noemailprefs": "이 기능을 사용하려면 사용자 환경 설정에서 이메일 주소를 지정하세요.",
        "grant-basic": "기본 권한",
        "grant-viewdeleted": "삭제된 파일과 문서 보기",
        "grant-viewmywatchlist": "내 주시문서 목록 보기",
+       "grant-viewrestrictedlogs": "제한된 로그 기록 보기",
        "newuserlogpage": "사용자 만들기 기록",
        "newuserlogpagetext": "사용자가 만들어진 기록입니다.",
        "rightslog": "사용자 권한 기록",
        "action-writeapi": "API를 작성할",
        "action-delete": "이 문서 삭제하기",
        "action-deleterevision": "판을 삭제",
+       "action-deletelogentry": "로그 기록 삭제",
        "action-deletedhistory": "문서의 삭제된 기여의 역사 보기",
+       "action-deletedtext": "삭제된 판의 문자열 보기",
        "action-browsearchive": "삭제된 문서 검색",
        "action-undelete": "문서 되살리기",
-       "action-suppressrevision": "ì\9d´ ì\88¨ê²¨ì§\84 í\8c\90ì\9d\84 ê²\80í\86 í\95\98ê³  ë\90\98ì\82´ë¦´",
+       "action-suppressrevision": "ì\9d´ ì\88¨ê²¨ì§\84 í\8c\90ì\9d\84 ê²\80í\86 í\95\98ê³  ë³µêµ¬í\95\98기",
        "action-suppressionlog": "비공개 기록 보기",
        "action-block": "이 사용자가 편집하지 못하도록 차단",
        "action-protect": "이 문서의 보호 설정을 바꾸기",
        "action-userrights-interwiki": "다른 위키의 사용자 권한을 조정",
        "action-siteadmin": "데이터베이스를 잠그거나 잠금 해제하기",
        "action-sendemail": "이메일 보내기",
+       "action-editmyoptions": "자신의 환경 설정 편집",
        "action-editmywatchlist": "내 주시문서 목록 편집",
        "action-viewmywatchlist": "내 주시문서 목록 보기",
        "action-viewmyprivateinfo": "자신의 개인정보 보기",
        "pageinfo-length": "문서 길이 (바이트)",
        "pageinfo-article-id": "문서 ID",
        "pageinfo-language": "문서 내용 언어",
+       "pageinfo-language-change": "바꾸기",
        "pageinfo-content-model": "문서 내용 모델",
        "pageinfo-content-model-change": "변경",
        "pageinfo-robot-policy": "로봇에 의한 색인",
        "restrictionsfield-badip": "유효하지 않은 IP 주소나 대역: $1",
        "restrictionsfield-label": "허용된 IP 대역:",
        "restrictionsfield-help": "줄 단위의 하나의 IP 주소 또는 CIDR 대역입니다. 모든 곳에 적용하려면, 다음을 사용하세요<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "$1 판",
        "pageid": "페이지 ID $1"
 }
index 817902b..51b0ccc 100644 (file)
        "pageinfo-length": "Gréisst vun der Säit (a Bytes)",
        "pageinfo-article-id": "ID (Nummer) vun der Säit",
        "pageinfo-language": "Sprooch vum Inhalt vun der Säit",
+       "pageinfo-language-change": "änneren",
        "pageinfo-content-model": "Modell vun enger Säit mat Inhalt",
        "pageinfo-content-model-change": "änneren",
        "pageinfo-robot-policy": "Indexéierung duerch Botten",
        "userjsispublic": "DEnkt drun: Op JavaScript-Ënnersäite solle keng vertraulech Informatioune stoe well se vun anere Benotzer kënne gesi ginn.",
        "restrictionsfield-badip": "Net valabel IP-Adress oder Beräich: $1",
        "restrictionsfield-label": "Zougeloossen IP-Beräicher:",
-       "revid": "r$1"
+       "revid": "Versioun $1"
 }
index ef2a562..54bd07e 100644 (file)
        "sort-descending": "Ordine decrescente",
        "sort-ascending": "Ordine crescente",
        "nstab-main": "Pàgina",
-       "nstab-user": "Utente",
+       "nstab-user": "Paggina utente",
        "nstab-media": "File murtimediâ",
        "nstab-special": "Pàgina speçiâ",
        "nstab-project": "Paggina de servissio",
        "tooltip-t-print": "Verscion stanpabbile de sta paggina",
        "tooltip-t-permalink": "Colegaménto fisso a sta revixión da pàgina",
        "tooltip-ca-nstab-main": "Véddi a vôxe",
-       "tooltip-ca-nstab-user": "Veddi a pàgina d'utente",
+       "tooltip-ca-nstab-user": "Amîa a paggina utente",
        "tooltip-ca-nstab-media": "Veddi a paggina do file murtimediâ",
        "tooltip-ca-nstab-special": "Sta chi l'è 'na pàgina speciâle e a no peu êse cangiâ",
        "tooltip-ca-nstab-project": "Veddi a paggina de servissio",
index 47791ce..31d3584 100644 (file)
@@ -33,6 +33,7 @@
        "tog-enotifminoredits": "ອີເມລຫາເຊັ່ນກັນສຳລັບການແກ້ໄຂໜ້າແລະໄຟລ໌ເລັກນ້ອຍ",
        "tog-enotifrevealaddr": "ເປີດເຜີຍທີ່ຢູ່ອີເມລຂອງຂ້ອຍໃນອີເມລແຈ້ງເຕືອນ",
        "tog-shownumberswatching": "ສະແດງຈຳນວນຜູ້ໃຊ້ທີ່ຕິດຕາມ",
+       "tog-oldsig": "ລາຍເຊັນຂອງທ່ານທີ່ມີຢູ່:",
        "tog-fancysig": "ຖືລາຍເຊັນເປັນຂໍ້ຄວາມວິກິ (ໂດຍບໍ່ມີລິງຄ໌ອັດຕະໂນມັດ)",
        "tog-uselivepreview": "ໃຊ້ການສະແດງໂຕຢ່າງແບບສົດ",
        "tog-forceeditsummary": "ເຕືອນເມື່ອຊ່ອງຄຳອະທິບາຍໂດຍຫຍໍ້ວ່າງເປົ່າ",
        "talk": "ສົນທະນາ",
        "views": "ເທື່ອເບິ່ງ",
        "toolbox": "ເຄື່ອງມື",
+       "tool-link-emailuser": "ສົ່ງອີເມວຫາ{{GENDER:$1|ຜູ້ໃຊ້}}ນີ້",
        "userpage": "ເບິ່ງໜ້າສົນທະນາຂອງຜູ້ໃຊ້",
        "projectpage": "ເບິ່ງໝ້າໂຄງການ",
        "mediawikipage": "ເບິ່ງ ໝ້າຂໍ້ຄວາມ",
        "privacy": "ນະໂຍບາຍຄວາມເປັນສ່ວນຕົວ",
        "privacypage": "Project:ນະໂຍບາຍຄວາມເປັນສ່ວນຕົວ",
        "badaccess": "ການອະນຸມັດບໍ່ຖືກຕ້ອງ",
-       "badaccess-group0": "ທ່ານ ບໍ່ໄດ້ຮັບອະນຸຍາດ ໃຫ້ປະຕິບັດການ ທີ່ ທ່ານ ສັ່ງ.",
+       "badaccess-group0": "ທ່ານບໍ່ໄດ້ຮັບອະນຸຍາດໃຫ້ປະຕິບັດການຕາມທີ່ທ່ານຮ້ອງຂໍໄວ້.",
        "versionrequired": "ຕ້ອງການເວີຣ໌ຊັ່ນ $1 ຂອງມີເດຍວິກິ",
        "ok": "ຕົກລົງ",
        "retrievedfrom": "ດຶງຂໍ້ມູນຈາກ \"$1\"",
        "readonly": "ຖານຂໍ້ມູນຖືກລອັກ",
        "enterlockreason": "ກະລຸນາຂຽນເຫດຜົນໃນການລອັກ, ລວມທັງ ປະມານເວລາທີ່ຈະປົດລອັກ",
        "missingarticle-diff": "(ສ່ວນຕ່າງ: $1, $2)",
+       "readonly_lag": "ຖານຂໍ້ມຸນໄດ້ຖືກລັອກແລ້ວໂດຍອັດຕະໂນມັດຂະນະທີ່ເຊີເວີ slave database ຖືກຈັບໃຫ້ອັນຫຼັກ",
        "internalerror": "ມີຄວາມຜິດພາດພາຍໃນ",
        "filerenameerror": "ບໍ່ສາມາດ ປ່ຽນ ຊື່ໄຟລ໌  \"$1\" ໄປເປັນ  \"$2\" ໄດ້.",
        "cannotdelete": "ບໍ່ສາມາດລຶບໜ້າຫຼືໄຟລ໌ \"$1\" ໄດ້.\nມັນອາດຈະຖືກລຶບໂດຍໃຜຜູ້ໜຶ່ງແລ້ວ.",
index 12b6ad5..e69632a 100644 (file)
        "views": "Peržiūros",
        "toolbox": "Įrankiai",
        "tool-link-userrights": "Keisti {{GENDER:$1|naudotojo|naudotojos}} grupes",
+       "tool-link-userrights-readonly": "Žiūrėti {{GENDER:$1|vartotojo|vartotojos}} grupes",
        "tool-link-emailuser": "Siųsti {{GENDER:$1|šiam naudotojui|šiai naudotojai}} el. laišką",
        "userpage": "Rodyti naudotojo puslapį",
        "projectpage": "Rodyti projekto puslapį",
        "ok": "Gerai",
        "retrievedfrom": "Gauta iš „$1“",
        "youhavenewmessages": "Jūs turite $1 ($2).",
-       "youhavenewmessagesfromusers": "Jūs gavote $1 nuo {{PLURAL:$3|kito naudotojo|$3 naudotojų}} ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Jūs gavote}} $1 iš {{PLURAL:$3|kito naudotojo|$3 naudotojų}} ($2).",
        "youhavenewmessagesmanyusers": "Jūs turite $1 iš daugelio vartotojų ( $2 ) .",
        "newmessageslinkplural": "{{PLURAL:$1|nauja žinutė|999=naujos žinutės}}",
        "newmessagesdifflinkplural": "paskutinis {{PLURAL:$1|pakeitimas|999=pakeitimai}}",
        "editusergroup": "Redaguoti {{GENDER:$1|naudotojo}} grupes",
        "editinguser": "Redaguojamos {{GENDER:$1|naudotojo}} <strong>[[User:$1|$1]]</strong> $2 teisės",
        "userrights-editusergroup": "Redaguoti naudotojų grupes",
+       "userrights-viewusergroup": "Žiūrėti naudotojo grupes",
        "saveusergroups": "Saugoti {{GENDER:$1|naudotojo}} grupes",
        "userrights-groupsmember": "Narys:",
        "userrights-groupsmember-auto": "Narys automatiškai:",
        "action-deletelogentry": "trinti žurnalo įrašus",
        "action-deletedhistory": "žiūrėti puslapio ištrintą istoriją",
        "action-browsearchive": "ieškoti ištrintų puslapių",
-       "action-undelete": "atkurti šį puslapį",
+       "action-undelete": "atkurti puslapius",
        "action-suppressrevision": "peržiūrėti ir atkurti šią paslėptą versiją",
        "action-suppressionlog": "peržiūrėti šį privatų registrą",
        "action-block": "neleisti šiam naudotojui redaguoti",
        "apisandbox-alert-field": "Šio lauko reikšmė yra neteisinga.",
        "apisandbox-continue": "Tęsti",
        "apisandbox-continue-clear": "Išvalyti",
+       "apisandbox-multivalue-all-values": "$1 (Visos reikšmės)",
        "booksources": "Knygų šaltiniai",
        "booksources-search-legend": "Knygų šaltinių paieška",
        "booksources-search": "Ieškoti",
        "pageinfo-length": "Puslapio ilgis (baitais)",
        "pageinfo-article-id": "Puslapio ID",
        "pageinfo-language": "Puslapio turinio kalba",
+       "pageinfo-language-change": "keisti",
        "pageinfo-content-model": "Puslapio turinio modelis",
        "pageinfo-content-model-change": "keisti",
        "pageinfo-robot-policy": "Robotų indeksavimas",
        "htmlform-user-not-exists": "<strong>$1</strong> neegzistuoja.",
        "htmlform-user-not-valid": "<strong>$1</strong> nėra tinkamas naudotojo vardas.",
        "logentry-delete-delete": "$1 {{GENDER:$2|ištrynė}} puslapį $3",
+       "logentry-delete-delete_redir": "$1 pervadindamas {{GENDER:$2|ištrynė}} buvusį nukreipimą $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|atkūrė}} puslapį $3",
        "logentry-delete-event": "$1 {{GENDER:$2|pakeitė}} matomumą {{PLURAL:$5|žurnalo įvykio|$5 žurnalo įvykių}} $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|pakeitė}} matomumą {{PLURAL:$5|versijos|$5 versijų}} puslapyje $3: $4",
        "special-characters-title-emdash": "em brūkšnys",
        "special-characters-title-minus": "minuso ženklas",
        "mw-widgets-dateinput-no-date": "Nepasirinkta data",
+       "mw-widgets-mediasearch-noresults": "Rezultatų nerasta.",
        "mw-widgets-titleinput-description-new-page": "puslapis dar neegzistuoja",
        "mw-widgets-titleinput-description-redirect": "nukreipti į $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Pridėti kategoriją...",
        "sessionmanager-tie": "Negalima kombinuoti kelių užklausų autentikacijos tipų: $1.",
        "sessionprovider-generic": "$1 sesijos",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "sesijos su slapukais",
        "authprovider-resetpass-skip-help": "Praleisti slaptažodžio perstatymą.",
        "specialpage-securitylevel-not-allowed-title": "Neleidžiama",
        "specialpage-securitylevel-not-allowed": "Apgailestaujame, tačiau jūs negalite naudotis šiuo puslapiu, nes nepavyko patvirtinti jūsų tapatybės.",
+       "authpage-cannot-login": "Negalima pradėti prisijungimo.",
+       "authpage-cannot-login-continue": "Negalima tęsti prisijungimo. Greičiausiai baigėsi jūsų sesijos laikas.",
+       "authpage-cannot-create": "Nepavyko pradėti paskyros kūrimo.",
+       "authpage-cannot-create-continue": "Negalima tęsti paskyros kūrimo. Greičiausiai baigėsi jūsų sesijos laikas.",
+       "authpage-cannot-link": "Nepavyko pradėti paskyros susiejimo.",
+       "authpage-cannot-link-continue": "Negalima tęsti paskyros susiejimo. Greičiausiai baigėsi jūsų sesijos laikas.",
        "cannotauth-not-allowed-title": "Teisė nesuteikta",
        "cannotauth-not-allowed": "Jūs negalite naudotis šiuo puslapiu",
        "credentialsform-account": "Paskyros vardas:",
        "linkaccounts-success-text": "Paskyra buvo susieta.",
        "linkaccounts-submit": "Susieti paskyras",
        "unlinkaccounts": "Atsieti paskyras",
-       "unlinkaccounts-success": "Paskyra buvo atsieta."
+       "unlinkaccounts-success": "Paskyra buvo atsieta.",
+       "revid": "apžvalga $1",
+       "pageid": "puslapio ID $1"
 }
index 233b95f..3cfe703 100644 (file)
        "preview": "Pirmskats",
        "showpreview": "Rādīt pirmskatu",
        "showdiff": "Rādīt izmaiņas",
-       "anoneditwarning": "'''Uzmanību:''' tu neesi iegājis. Lapas hronoloģijā tiks ierakstīta tava IP adrese.",
+       "anoneditwarning": "<strong>Uzmanību:</strong> tu neesi pieslēdzies. Ja veiksi labojumus, publiski būs redzama tava IP adrese. Ja tu <strong>[$1 pieslēgsies]</strong> vai <strong>[$2 izveidosi kontu]</strong>, visi labojumi tiks piesaistīti tavam kontam; būs arī citi ieguvumi.",
        "anonpreviewwarning": "''Tu neesi ienācis. Saglabājot lapu, Tava IP adrese tiks ierakstīta šīs lapas hronoloģijā.''",
        "missingsummary": "'''Atgādinājums''': Tu neesi norādījis izmaiņu kopsavilkumu. Vēlreiz klikšķinot uz \"Saglabāt lapu\", Tavas izmaiņas tiks saglabātas bez kopsavilkuma.",
        "missingcommenttext": "Lūdzu, ievadi tekstu zemāk redzamajā logā!",
        "specialpages-group-login": "Pieslēgties / izveidot kontu",
        "specialpages-group-changes": "Pēdējās izmaiņas un reģistri",
        "specialpages-group-media": "Failu atskaites un augšuplāde",
-       "specialpages-group-users": "Lietotāji un piekļuves tiesības",
+       "specialpages-group-users": "Dalībnieki un piekļuves tiesības",
        "specialpages-group-highuse": "Bieži izmantotās lapas",
        "specialpages-group-pages": "Lapu saraksti",
        "specialpages-group-pagetools": "Lapu rīki",
index 831218c..bf65c6d 100644 (file)
        "blockedtitle": "Корисникот е блокиран",
        "blockedtext": "'''Вашето корисничко име или IP-адреса е блокирано.'''\n\nБлокирањето е направено од страна на $1.\nДаденото образложение е ''$2''.\n\n* Почеток на блокирањето: $8\n* Истекување на блокирањето: $6\n* Корисникот што требало да биде блокиран: $7\n\nМоже да контактирате со $1 или некој друг [[{{MediaWiki:Grouppage-sysop}}|администратор]] за да разговарате во врска со блокирањето.\nМожете да ја искористите можноста „Е-пошта до овој корисник“ ако е назначена важечка е-поштенска адреса во [[Special:Preferences|вашите нагодувања]] и не ви е забрането да ја користите.\nВашата сегашна IP-адреса е $3, а назнака на блокирањето гласи #$5.\nВе молиме наведете ги сите подробности прикажани погоре, во вашата евентуална реакција.",
        "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, a ID на блокирањеto е $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 за да уредувате страници.",
        "confirmedittext": "Морате да ја потврдите вашата е-поштенска адреса пред да уредувате страници.\nПоставете ја и валидирајте ја вашата е-поштенска адреса преку вашите [[Special:Preferences|нагодувања]].",
        "pageinfo-length": "Големина на страницата (во бајти)",
        "pageinfo-article-id": "Назнака на страницата",
        "pageinfo-language": "Јазик на содржината на страницата",
+       "pageinfo-language-change": "смени",
        "pageinfo-content-model": "Модел на содржината на страницата",
        "pageinfo-content-model-change": "смени",
        "pageinfo-robot-policy": "Индексирање со роботи",
        "restrictionsfield-badip": "Неважечки IP-дијапазон на адреси: $1",
        "restrictionsfield-label": "Допуштени IP-опсези:",
        "restrictionsfield-help": "Една IP-адреса или CIDR-опсег по ред. За да овозможите сè, користете<br><code>0.0.0.0/0</code><br><code>::/0</code>",
-       "revid": "п$1",
+       "revid": "преработка $1",
        "pageid": "назнака на страницата $1"
 }
index f0376cb..d47a5c6 100644 (file)
        "searchprofile-advanced-tooltip": "စိတ်ကြိုက်အမည်ညွှန်းများတွင် ရှာရန်",
        "search-result-size": "$1 ({{PLURAL:$2|စကားလုံး 1 လုံး|စကားလုံး $2 လုံး}})",
        "search-result-category-size": "{{PLURAL:$1|အသင်းဝင်တစ်ခု|အသင်းဝင် $1 ခု}} ({{PLURAL:$2|ကဏ္ဍခွဲတစ်ခု|ကဏ္ဍခွဲ $2 ခု}}, {{PLURAL:$3|ဖိုင်တစ်ခု|ဖိုင် $3 ခု}})",
-       "search-redirect": "($1 á\80\9eá\80­á\80¯á\80· á\80\95á\80¼á\80\94á\80ºá\80\8aá\80½á\80¾á\80\94á\80ºးသည်)",
+       "search-redirect": "($1 á\80\99á\80¾ á\80\95á\80¼á\80\94á\80ºá\80\8aá\80½á\80¾á\80\94á\80ºá\80¸á\80\91á\80¬းသည်)",
        "search-section": "(အပိုင်း $1)",
        "search-category": "(ကဏ္ဍ $1)",
        "search-suggest": "$1 ဟု ဆိုလိုပါသလား။",
        "prefs-tokenwatchlist": "တိုကင်",
        "prefs-diffs": "ကွဲပြားချက်",
        "userrights": "အသုံးပြုသူ၏ အခွင့်အရေးများကို စီမံခန့်ခွဲခြင်း",
-       "userrights-lookup-user": "á\80¡á\80\9eá\80¯á\80¶á\80¸á\80\95á\80¼á\80¯á\80\9eá\80°á\80¡á\80¯á\80\95á\80ºá\80\85á\80¯á\80\80á\80­á\80¯ á\80\85á\80®á\80\99á\80ရန်",
+       "userrights-lookup-user": "á\80¡á\80\9eá\80¯á\80¶á\80¸á\80\95á\80¼á\80¯á\80\9eá\80°á\80\90á\80\85á\80ºá\80¦á\80¸á\80\80á\80­á\80¯ á\80\9bá\80½á\80±á\80¸á\80\81á\80»á\80\9aá\80ºရန်",
        "userrights-user-editname": "အသုံးပြုသူအမည်တစ်ခုကို ထည့်ပါ -",
-       "editusergroup": "{{GENDER:$1|အသုံးပြုသူ}}အုပ်စုများကို တည်းဖြတ်ရန်",
+       "editusergroup": "အသုံးပြုသူအုပ်စုကို ဖော်ပြရန်",
        "editinguser": "{{GENDER:$1|အသုံးပြုသူ}} <strong>[[User:$1|$1]]</strong> $2 ၏ အသုံးပြုအခွင့်အရေးများကို ပြောင်းလဲခြင်း",
        "userrights-editusergroup": "အသုံးပြုသူအုပ်စုကို တည်းဖြတ်ရန်",
        "saveusergroups": "{{GENDER:$1|အသုံးပြုသူ}}အုပ်စုများကို သိမ်းရန်",
        "userrights-groupsmember": "အဖွဲ့ဝင်",
        "userrights-reason": "အ​ကြောင်း​ပြ​ချက်:",
-       "userrights-notallowed": "သင့်တွင် အသုံးပြုသူအခွင့်အရေး ပေါင်းထည့်ရန်  သို့ ဖယ်ရှားရန် အခွင့်အရေး မရှိပါ။",
        "userrights-changeable-col": "သင်ပြောင်းလဲပေးနိုင်သောအုပ်စုများ",
        "userrights-unchangeable-col": "သင်ပြောင်းလဲမပေးနိုင်သောအုပ်စုများ",
        "group": "အုပ်စု -",
        "action-reupload": "ဤရှိပြီးသားဖိုင်ကို ထပ်ရေးရန်",
        "action-writeapi": "ရေးသားမှု API ကို သုံးရန်",
        "action-delete": "ဤစာမျက်နှာကို ဖျက်ရန်",
-       "action-deleterevision": "á\80¤á\80\99á\80°ကို ဖျက်ရန်",
-       "action-deletedhistory": "á\80¤á\80\85á\80¬á\80\99á\80»á\80\80á\80ºá\80\94á\80¾á\80¬á\81\8fဖျက်လိုက်သောရာဇဝင်ကို ကြည့်ရန်",
+       "action-deleterevision": "á\80\99á\80°á\80\99á\80»á\80¬á\80¸ကို ဖျက်ရန်",
+       "action-deletedhistory": "á\80\85á\80¬á\80\99á\80»á\80\80á\80ºá\80\94á\80¾á\80¬á\80\90á\80\85á\80ºá\80\81á\80¯á\81\8f ဖျက်လိုက်သောရာဇဝင်ကို ကြည့်ရန်",
        "action-browsearchive": "ဖျက်ပစ်လိုက်သော စာမျက်နှာများကို ရှာရန်",
-       "action-undelete": "á\80¤á\80\85á\80¬á\80\99á\80»á\80\80á\80ºá\80\94á\80¾á\80¬á\80\80á\80­á\80¯ မဖျက်တော့ရန်",
+       "action-undelete": "á\80\85á\80¬á\80\99á\80»á\80\80á\80ºá\80\94á\80¾á\80¬á\80\99á\80»á\80¬á\80¸ á\80\95á\80¼á\80\94á\80ºမဖျက်တော့ရန်",
        "action-suppressionlog": "ဤကိုယ်ပိုင်မှတ်တမ်းကို ကြည့်ရန်",
        "action-block": "တည်းဖြတ်ခြင်းမှ ဤအသုံးပြုသူကို ပိတ်ပင်ရန်",
        "action-protect": "ဤစာမျက်နှာအတွက် ကာကွယ်မှုအဆင့်ကို ပြောင်းလဲရန်",
        "rcshowhideminor-hide": "ဝှက်",
        "rcshowhidebots": "ဘော့များ $1ရန်",
        "rcshowhidebots-show": "ပြ",
-       "rcshowhidebots-hide": "ဝှက်ရန်",
+       "rcshowhidebots-hide": "ဝှက်",
        "rcshowhideliu": "မှတ်ပုံတင်ထားသော အသုံးပြုသူများ $1",
        "rcshowhideliu-show": "ပြသရန်",
        "rcshowhideliu-hide": "ဝှက်",
        "logentry-upload-overwrite": "$3 ၏ ဗားရှင်းအသစ်ကို $1 {{GENDER:$2|upload တင်ခဲ့သည်}}",
        "rightsnone": "(ဘာမှမရှိ)",
        "revdelete-summary": "အကျဉ်းချုပ်ကို တည်းဖြတ်ရန်",
-       "searchsuggest-search": "ရှာဖွေရန်",
+       "searchsuggest-search": "{{SITENAME}} တွင် ရှာဖွေရန်",
        "api-error-filename-tooshort": "ဖိုင်အမည်သည် တိုလွန်းသည်။",
        "api-error-filetype-banned": "ဤဖိုင်အမျိုးအစားကို တားမြစ်ထားသည်။",
        "api-error-http": "အတွင်းပိုင်းအမှား - ဆာဗာကို မဆက်သွယ်နိုင်ပါ။",
index 6cb3e84..6c21e03 100644 (file)
        "january-gen": "Ic cē mētztli",
        "february-gen": "Īcōmemētztli",
        "march-gen": "Īcyēyimētztli",
-       "april-gen": "Ic nāuhtetl mētztli",
+       "april-gen": "Ic nauhtetl metztli",
        "may-gen": "Īcmācuīllimētztli",
-       "june-gen": "Ic chicuacemmētztli",
-       "july-gen": "Ic chicōme mētztli",
+       "june-gen": "Ic chicuacemmetztli",
+       "july-gen": "Ic chicome metztli",
        "august-gen": "Īcchicuēyimētztli",
        "september-gen": "Īcchiucnāhuimētztli",
        "october-gen": "Īcmahtlāctetlmētztli",
        "category-media-header": "Media \"$1\" ipan neneuhcayotl",
        "category-empty": "''Ahtle oncah ipan neneuhcayotl.''",
        "hidden-categories": "{{PLURAL:$1|tlatlatilli neneuhcayotl|tlatlatiltin neneuhcayomeh}}",
-       "hidden-category-category": "Tlatlàtìlkàtlaìxmatkàtlàlilòmë",
+       "hidden-category-category": "Tlahyanalli neneuhcayotl",
        "category-subcat-count": "{{PLURAL:$2|Inin neneuhcayotl zan quipiya in tetoquilli tlani-neneuhcayotl.|Inin neneuhcayotl {{PLURAL:$1|quipiya in tetoquilli tlani-neneuhcayotl|in tetoquiltin $1 tlani-neneuhcayomeh}}, itech tlacecempohualoni $2.}}",
        "category-subcat-count-limited": "Inin {{PLURAL:$1|neneuhcayotl quipiya|$1 in tetoquilli tlani-neneuhcayotl|in tetoquiltin tlani-neneuhcayomeh}}.",
        "category-article-count": "{{PLURAL:$2|Inin neneuhcayotl zan quipiya in tetoquilli tlahcuilolli.|{{PLURAL:$1|In tetoquilli tlahcuilolli itech pohui|In tetoquiltin $1 tlahcuiloltin itech pohui}}, inin neneuhcayotl itech tlacecempohualoni ipan $2.}}",
        "category-article-count-limited": "Inīn {{PLURAL:$1|zāzanilli cah|$1 zāzanilli cateh}} inīn neneuhcāyōc.",
        "category-file-count": "{{PLURAL:$2|Inìn tlaìxmatkàyòtlàlilòtl san kipia|Inìn tlaìxmatkàyòtlalilòtl kimpia {{PLURAL:$1|inìn èwalli|inîke $1 èwaltìn}}, ìwikpa $2.}}",
-       "category-file-count-limited": "{{PLURAL:$1|Inìn tlâkuilòlèwalli kä|Inîkë $1 tlâkuilòlèwaltìn katêkë}} ìpan inìn tlaìxmatkàtlàlilòtl.",
+       "category-file-count-limited": "{{PLURAL:$1|Inin tlahcuilolehualli kah|Inihqueh $1 tlahcuilolehualtin catehqueh}} ipan inin neneuhcayotl.",
        "listingcontinuesabbrev": "niman",
        "about": "Itechcopa",
        "article": "Tlahcuilolamatl",
        "newpage": "Yancuic tlahcuilolli",
        "talkpage": "Xictlahto inīn tlaīxtli ītechcopa",
        "talkpagelinktext": "Teixnamiquiliztli",
-       "specialpage": "Nònkuâkìskàtlaìxtlapalli",
+       "specialpage": "Noncuahquizcatlahcuilolamatl",
        "personaltools": "In tlein nitēquitiltilia",
        "articlepage": "Xiquitta tlahcuilolamatl",
        "talk": "Teixnamiquiliztli",
        "nstab-project": "Ìtlaìxtlapal in tlayẻkàntekitl",
        "nstab-image": "Tlahcuilolpiyalli",
        "nstab-mediawiki": "Tlahcuilōltzintli",
-       "nstab-template": "Nemachiòtl",
+       "nstab-template": "Nemachiyotilli",
        "nstab-help": "Tèpalèwilistli",
        "nstab-category": "Neneuhcayotl",
        "mainpage-nstab": "Yacatlahcuilolli",
        "shown-title": "Monextiz $1 {{PLURAL:$1|mochihualiztli}} cecen amatl",
        "viewprevnext": "Xiquintta ($1 {{int:pipe-separator}} $2) ($3).",
        "searchmenu-exists": "'''Ye ia zāzanilli ītōca \"[[$1]]\" inīn huiquipan'''",
-       "searchmenu-new": "<strong>Ticchīhuāz in zāzanilli «[[:$1]]» inīn huiquipan.</strong> {{PLURAL:$2|0=|Nō xiquitta in tlanāmiquiliztli in mochīhualiztli.}}",
+       "searchmenu-new": "<strong>Ticchihuaz in tlahcuilolamatl «[[:$1]]» inin huiquipan.</strong> {{PLURAL:$2|0=|No xiquitta in tlanamiquiliztli itech tlatemoliztli.}}",
        "searchprofile-articles": "Itech tlahcuilolamatl",
        "searchprofile-images": "Nepapan media",
        "searchprofile-everything": "Mochi",
        "withoutinterwiki-submit": "Tiquittāz",
        "nbytes": "$1 {{PLURAL:$1|byte}}",
        "ncategories": "$1 {{PLURAL:$1|tlaìxmatkàyòtlàlilòtl|tlaìxmatkàyòtlàlilòme}}",
-       "nlinks": "$1 {{PLURAL:$1|tzòwilistli|tzòwilistìn}}",
+       "nlinks": "$1 {{PLURAL:$1|tzohuililiztli|tzohuililiztin}}",
        "nmembers": "$1 {{PLURAL:$1|tlahcuilolamatl|tlahcuilolamameh}}",
        "nrevisions": "$1 {{PLURAL:$1|tlapiyaliztli}}",
        "nimagelinks": "Motekìuhtia ìpan $1 {{PLURAL:$1|tlaìxtlapalli|tlaìxtlapaltìn}}",
        "exif-gpslongitude": "Huehtlatzīncāyōtl",
        "exif-gpsaltitude": "Huehcapancayōtl",
        "exif-gpstimestamp": "GPS cāhuitl (atomic tepozcāhuitl)",
-       "exif-iimcategory": "Tlaìxmatkàyòtlàlilòtl",
+       "exif-iimcategory": "Neneuhcayotl",
        "exif-orientation-1": "Yēctli",
        "exif-meteringmode-255": "Occē",
        "exif-lightsource-1": "Tōnameyōtl",
index 01bcad4..3289b90 100644 (file)
        "blockedtitle": "Brukeren er blokkert",
        "blockedtext": "'''Ditt brukernavn eller din IP-adresse har blitt blokkert.'''\n\nBlokkeringen ble utført av $1. Grunnen som ble oppgitt var ''$2''.\n\n* Blokkeringen begynte: $8\n* Blokkeringen utgår: $6\n* Blokkering ment på: $7\n\nDu kan kontakte $1 eller en annen [[{{MediaWiki:Grouppage-sysop}}|administrator]] for å diskutere blokkeringen.\nDu kan ikke bruke «E-post til denne brukeren»-funksjonen med mindre du har oppgitt en gyldig e-postadresse i [[Special:Preferences|innstillingene dine]] og du ikke er blokkert fra å sende e-post.\nDin nåværende IP-adresse er $3, og blokkerings-ID-en er #$5.\nVennligst ta all denne informasjonen ved henvendelser.",
        "autoblockedtext": "Din IP-adresse har blitt automatisk blokkert fordi den ble brukt av en annen bruker som ble blokkert av $1.\nDen oppgitte grunnen var:\n\n:'''$2'''\n\n* Blokkeringen begynte: $8\n* Blokkeringen utgår: $6\n* Blokkeringen er ment for: $7\n\nDu kan kontakte $1 eller en av de andre [[{{MediaWiki:Grouppage-sysop}}|administratorene]] for å diskutere blokkeringen.\n\nMerk at du ikke kan bruke «E-post til denne brukeren»-funksjonen med mindre du har registrert en gyldig e-postadresse i [[Special:Preferences|innstillingene dine]].\n\nDin IP-adresse er $3, og blokkerings-ID-en er #$5.\nVennligst ta med all denne informasjonen ved henvendelser.",
+       "systemblockedtext": "Ditt brukernavn eller IP-adresse har blitt blokkert automatisk av MediaWiki.\n\nBlokkeringen grunnes:\n\n:<em>$2</em>\n\n* Blokaden startet: $8\n* Blokaden gjelder til: $6\n* Blokaden er ment for: $7\n\nDin nåværende IP-adresse er $3.\nVennligst inkluder informasjonen over i alle spørsmål du spør angående dette.",
        "blockednoreason": "ingen grunn gitt",
        "whitelistedittext": "Du må $1 for å redigere artikler.",
        "confirmedittext": "Du må bekrefte e-postadressen din før du kan redigere sider. Vennligst oppgi og bekreft e-postadressen din via [[Special:Preferences|innstillingene dine]].",
        "pageinfo-length": "Sidestørrelse (i bytes)",
        "pageinfo-article-id": "Side-ID",
        "pageinfo-language": "Språk for sideinnholdet",
+       "pageinfo-language-change": "endre",
        "pageinfo-content-model": "Modell for sideinnhold",
        "pageinfo-content-model-change": "endre",
        "pageinfo-robot-policy": "Bot-indeksering",
        "restrictionsfield-badip": "Ugyldig IP-adresse eller intervall: $1",
        "restrictionsfield-label": "Tillatte IP-intervaller:",
        "restrictionsfield-help": "Én IP-adresse eller CIDR-intervall per linje. For å slå på alt, bruk <br /><code>0.0.0.0/0</code><br /><code>::/0</code>",
+       "revid": "revisjon $1",
        "pageid": "side-ID $1"
 }
index 528d6ee..420c5b5 100644 (file)
@@ -81,7 +81,8 @@
                        "Jeleniccz",
                        "MrLeopold",
                        "Hex",
-                       "Xxmarijnw"
+                       "Xxmarijnw",
+                       "Mainframe98"
                ]
        },
        "tog-underline": "Koppelingen onderstrepen:",
        "unprotectthispage": "Beveiliging van deze pagina wijzigen",
        "newpage": "Nieuwe pagina",
        "talkpage": "Overlegpagina",
-       "talkpagelinktext": "Overleg",
+       "talkpagelinktext": "overleg",
        "specialpage": "Speciale pagina",
        "personaltools": "Persoonlijke instellingen",
        "articlepage": "Pagina bekijken",
        "pool-servererror": "De dienst \"pool counter\" is niet beschikbaar ($1).",
        "poolcounter-usage-error": "Gebruiksfout: $1",
        "aboutsite": "Over {{SITENAME}}",
-       "aboutpage": "Project:Info",
+       "aboutpage": "Project:Over",
        "copyright": "De inhoud is beschikbaar onder de $1 tenzij anders aangegeven.",
        "copyrightpage": "{{ns:project}}:Auteursrechten",
        "currentevents": "In het nieuws",
        "blockedtitle": "Gebruiker is geblokkeerd",
        "blockedtext": "'''Uw gebruiker of IP-adres is geblokkeerd.'''\n\nDe blokkade is uitgevoerd door $1.\nDe opgegeven reden is ''$2''.\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt contact opnemen met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] om de blokkade te bespreken.\nU kunt geen gebruik maken van de functie \"Deze gebruiker e-mailen\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]] en het gebruik van deze functie niet geblokkeerd is.\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.",
        "autoblockedtext": "Uw IP-adres is automatisch geblokkeerd, omdat het is gebruikt door een andere gebruiker, die is geblokkeerd door $1.\nDe opgegeven reden is:\n\n:''$2''\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nU kunt deze blokkade bespreken met $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheerder]].\n\nU kunt geen gebruik maken van de functie \"Deze gebruiker e-mailen\", tenzij u een geldig e-mailadres hebt opgegeven in uw [[Special:Preferences|voorkeuren]] en het gebruik van deze functie niet is geblokkeerd.\n\nUw huidige IP-adres is $3 en het blokkadenummer is #$5.\nVermeld alle bovenstaande gegevens als u ergens op deze blokkade reageert.",
+       "systemblockedtext": "Uw gebruikersnaam of IP-adres is automatisch geblokkeerd door MediaWiki.\nDe opgegeven reden is:\n\n:<em>$2</em>\n\n* Aanvang blokkade: $8\n* Einde blokkade: $6\n* Bedoeld te blokkeren: $7\n\nUw huidige IP-adres is $3.\nVermeld alle bovenstaande gegevens in een query die u maakt.",
        "blockednoreason": "geen reden opgegeven",
        "whitelistedittext": "U moet $1 om pagina's te bewerken.",
        "confirmedittext": "U moet uw e-mailadres bevestigen voor u kunt bewerken.\nVoer uw e-mailadres in en bevestig het via uw [[Special:Preferences|voorkeuren]].",
        "search-external": "Extern zoeken",
        "searchdisabled": "Zoeken in {{SITENAME}} is niet mogelijk.\nU kunt gebruik maken van Google.\nDe gegevens over {{SITENAME}} zijn mogelijk niet bijgewerkt.",
        "search-error": "Er is een fout opgetreden tijdens het zoeken: $1",
+       "search-warning": "Een waarschuwing is opgetreden tijdens het zoeken: $1",
        "preferences": "Voorkeuren",
        "mypreferences": "Voorkeuren",
        "prefs-edits": "Aantal bewerkingen:",
        "prefs-help-recentchangescount": "Dit geldt voor recente wijzigingen, paginageschiedenis en logboekpagina's.",
        "prefs-help-watchlist-token2": "Dit is de geheime sleutel voor de webfeed van uw volglijst.\nIedereen die het token kent, kan uw volglijst bekijken, dus deel dit token niet.\nU kunt de [[Special:ResetTokens|tokens opnieuw instellen]] als u dat wilt.",
        "savedprefs": "Uw voorkeuren zijn opgeslagen.",
-       "savedrights": "De gebruikersrechten van {{GENDER:$1|$1}} zijn opgeslagen.",
+       "savedrights": "De gebruikergroepen van {{GENDER:$1|$1}} zijn opgeslagen.",
        "timezonelegend": "Tijdzone:",
        "localtime": "Plaatselijke tijd:",
        "timezoneuseserverdefault": "Wikistandaard gebruiken ($1)",
        "userrights": "Gebruikersrechtenbeheer",
        "userrights-lookup-user": "Een gebruiker selecteren",
        "userrights-user-editname": "Voer een gebruikersnaam in:",
-       "editusergroup": "{{GENDER:$1|Gebruikersgroepen}} wijzigen",
+       "editusergroup": "Gebruikersgroepen wijzigen",
        "editinguser": "Bezig met wijzigen van de gebruikersrechten van gebruiker '''[[User:$1|$1]]''' $2",
+       "viewinguserrights": "Gebruikersrechten bekijken van {{GENDER:$1|gebruiker}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "Gebruikersgroepen wijzigen",
+       "userrights-viewusergroup": "Toon gebruikersgroepen",
        "saveusergroups": "{{GENDER:$1|Gebruikersgroepen}} opslaan",
        "userrights-groupsmember": "Lid van:",
        "userrights-groupsmember-auto": "Impliciet lid van:",
        "action-upload_by_url": "dit bestand vanaf een URL te uploaden",
        "action-writeapi": "via de API bewerkingen uit te voeren",
        "action-delete": "deze pagina te verwijderen",
-       "action-deleterevision": "deze versie te verwijderen",
-       "action-deletedhistory": "de verwijderde versies van deze pagina te bekijken",
+       "action-deleterevision": "verwijder versies",
+       "action-deletelogentry": "logboekregels te verwijderen",
+       "action-deletedhistory": "de verwijderde versies van een pagina te bekijken",
+       "action-deletedtext": "de verwijderde versietekst te bekijken",
        "action-browsearchive": "verwijderde pagina's te zoeken",
        "action-undelete": "deze pagina terug te plaatsen",
-       "action-suppressrevision": "deze verborgen versie te bekijken en terug te plaatsen",
+       "action-suppressrevision": "verborgen versies te bekijken en terug te plaatsen",
        "action-suppressionlog": "dit beschermde logboek te bekijken",
        "action-block": "deze gebruiker een bewerkingsblokkade op te leggen",
        "action-protect": "het beveiligingsniveau van deze pagina aan te passen",
        "action-userrights-interwiki": "gebruikersrechten van gebruikers van andere wiki's te bewerken",
        "action-siteadmin": "de database af te sluiten of open te stellen",
        "action-sendemail": "e-mails te verzenden",
+       "action-editmyoptions": "uw eigen voorkeuren bewerken",
        "action-editmywatchlist": "uw eigen volglijst te bewerken",
        "action-viewmywatchlist": "uw eigen volglijst te bekijken",
        "action-viewmyprivateinfo": "uw eigen privégegevens te bekijken",
        "emailccsubject": "Kopie van uw bericht aan $1: $2",
        "emailsent": "E-mail verzonden",
        "emailsenttext": "Uw e-mail is verzonden.",
-       "emailuserfooter": "Deze e-mail is {{GENDER:$1|verstuurd}} door $1 aan {{GENDER:$2|$2}} door de functie \"{{int:emailuser}}\" van {{SITENAME}}.",
+       "emailuserfooter": "Deze e-mail is door $1 aan {{GENDER:$2|$2}} {{GENDER:$1|verstuurd}} middels de functie \"{{int:emailuser}}\" van {{SITENAME}}. {{GENDER:$2|Uw}} e-mail wordt direct naar de {{GENDER:$1|oorspronkelijke afzender}} verstuurd, waardoor {{GENDER:$2|uw}} e-mailadres aan {{GENDER:$1|hem|haar|hem of haar}} onthuld wordt.",
        "usermessage-summary": "Systeembericht achtergelaten",
        "usermessage-editor": "Systeembericht",
        "watchlist": "Volglijst",
        "sp-contributions-newonly": "Alleen nieuwe pagina's weergeven",
        "sp-contributions-hideminor": "Kleine bewerkingen verbergen",
        "sp-contributions-submit": "Bekijken",
-       "whatlinkshere": "Koppelingen naar deze pagina",
+       "whatlinkshere": "Verwijzingen naar deze pagina",
        "whatlinkshere-title": "Pagina's die verwijzen naar \"$1\"",
        "whatlinkshere-page": "Pagina:",
        "linkshere": "De volgende pagina's verwijzen naar '''[[:$1]]''':",
        "movelogpagetext": "Hieronder staan hernoemde pagina's.",
        "movesubpage": "{{PLURAL:$1|Subpagina|Subpagina's}}",
        "movesubpagetext": "De {{PLURAL:$1|subpagina|$1 subpagina's}} van deze pagina {{PLURAL:$1|wordt|worden}} hieronder weergegeven.",
+       "movesubpagetalktext": "De bijbehorende overlegpagina heeft $1 {{PLURAL:$1|deelpagina|deelpagina's}} hierbeneden getoond.",
        "movenosubpage": "Deze pagina heeft geen subpagina's.",
        "movereason": "Reden:",
        "revertmove": "terugdraaien",
        "tooltip-ca-move": "Deze pagina hernoemen",
        "tooltip-ca-watch": "Deze pagina aan mijn volglijst toevoegen",
        "tooltip-ca-unwatch": "Deze pagina van mijn volglijst verwijderen",
-       "tooltip-search": "Zoeken in {{SITENAME}}",
-       "tooltip-search-go": "Naar een pagina met deze naam gaan als die bestaat",
+       "tooltip-search": "Doorzoek {{SITENAME}}",
+       "tooltip-search-go": "Naar een pagina met deze naam gaan als deze bestaat",
        "tooltip-search-fulltext": "Alle pagina's op deze tekst doorzoeken",
        "tooltip-p-logo": "Naar de hoofdpagina gaan",
        "tooltip-n-mainpage": "Naar de hoofdpagina gaan",
        "pageinfo-length": "Paginalengte (in bytes)",
        "pageinfo-article-id": "Paginanummer",
        "pageinfo-language": "Taal voor de pagina",
+       "pageinfo-language-change": "wijzigen",
        "pageinfo-content-model": "Paginainhoudmodel",
        "pageinfo-content-model-change": "wijzigen",
        "pageinfo-robot-policy": "Indexering door robots",
        "pageinfo-category-pages": "Aantal pagina's",
        "pageinfo-category-subcats": "Aantal subcategorieën",
        "pageinfo-category-files": "Aantal bestanden",
+       "pageinfo-user-id": "Gebruikers-ID",
        "markaspatrolleddiff": "Als gecontroleerd markeren",
        "markaspatrolledtext": "Deze pagina als gecontroleerd markeren",
        "markaspatrolledtext-file": "Deze bestandsversie als gecontroleerd markeren",
        "confirmemail_body_set": "Iemand, waarschijnlijk u, met het IP-adres $1,\nheeft het e-mailadres voor gebruiker \"$2\" op {{SITENAME}} ingesteld op dit e-mailadres.\n\nOpen de volgende koppeling in uw webbrowser om te bevestigen dat u deze gebruiker bent en om de e-mailmogelijkheden op {{SITENAME}} opnieuw te activeren:\n\n$3\n\nAls deze gebruiker *niet* aan u toebehoort, klik dan op de volgende koppeling om de bevestiging van uw e-mailadres te annuleren:\n\n$5\n\nDe bevestigingscode vervalt op $4.",
        "confirmemail_invalidated": "De e-mailbevestiging is geannuleerd",
        "invalidateemail": "E-mailbevestiging annuleren",
+       "notificationemail_body_changed": "Iemand, waarschijnlijk u, met het IP-adres $1, heeft het e-mailadres van de gebruiker \"$2\" op {{SITENAME}} gewijzigd naar \"$3\". \n\nAls u dit niet was, neem dan onmiddellijk contact op met een sitebeheerder.",
        "notificationemail_body_removed": "Iemand, waarschijnlijk u, met het IP-adres $1, heeft het e-mailadres geregistreerd voor gebruiker \"$2\" verwijderd op {{SITENAME}}. \n\nAls u dit niet was, neem dan onmiddellijk contact op met een sitebeheerder.",
        "scarytranscludedisabled": "[Interwiki-invoeging van sjablonen is uitgeschakeld]",
        "scarytranscludefailed": "[De sjabloon $1 kon niet opgehaald worden]",
        "tags-delete-not-found": "Het label \"$1\" bestaat niet.",
        "tags-delete-too-many-uses": "Het label \"$1\" is toegepast op meer dan $2 {{PLURAL:$2|versies}}. Daardoor kan het niet verwijderd worden.",
        "tags-delete-warnings-after-delete": "Het label \"$1\" is verwijderd, maar de volgende {{PLURAL:$2|waarschuwing is|waarschuwingen zijn}} opgetreden:",
+       "tags-delete-no-permission": "U hebt geen rechten om wijzigingslabels te verwijderen.",
        "tags-activate-title": "Label activeren",
        "tags-activate-question": "U activeert het label \"$1\".",
        "tags-activate-reason": "Reden:",
        "htmlform-date-placeholder": "JJJJ-MM-DD",
        "htmlform-time-placeholder": "HH:MM:SS",
        "htmlform-datetime-placeholder": "JJJJ-MM-DD HH:MM:SS",
+       "htmlform-date-invalid": "De waarde die u hebt opgegeven is niet herkend als datum. Probeer het YYYY-MM-DD datumformaat.",
+       "htmlform-time-invalid": "De waarde die u hebt opgegeven is niet herkend als tijd. Probeer het HH:MM:SS tijdformaat.",
+       "htmlform-datetime-invalid": "De waarde die u hebt opgegeven is niet herkend als datum en tijd. Probeer het JJJJ-MM-DD HH:MM:SS formaat.",
+       "htmlform-date-toolow": "De waarde die u hebt opgegeven ligt voor de vroegste toegestane datum van $1.",
+       "htmlform-date-toohigh": "De waarde die u hebt opgegeven ligt na de laatste toegestane datum van $1.",
        "htmlform-title-badnamespace": "[[:$1]] bevindt zich niet in de naamruimte \"{{ns:$2}}\".",
        "htmlform-title-not-creatable": "\"$1\" is geen paginanaam die aangemaakt kan worden",
        "htmlform-title-not-exists": "$1 bestaat niet.",
        "feedback-thanks": "Bedankt! Uw terugkoppeling is op de pagina \"[$2 $1]\" geplaatst.",
        "feedback-thanks-title": "Bedankt!",
        "feedback-useragent": "Useragent:",
-       "searchsuggest-search": "Zoeken in {{SITENAME}}",
+       "searchsuggest-search": "Doorzoek {{SITENAME}}",
        "searchsuggest-containing": "bevat...",
+       "api-error-autoblocked": "Uw IP-adres is automatisch geblokeerd, omdat het gebruikt is door een geblokkeerde gebruiker.",
        "api-error-badaccess-groups": "U mag geen bestanden uploaden in deze wiki.",
        "api-error-badtoken": "Interne fout: het token klopt niet.",
        "api-error-blocked": "U bent geblokkeerd en kunt niet bewerken.",
        "mw-widgets-dateinput-no-date": "Geen datum geselecteerd",
        "mw-widgets-dateinput-placeholder-day": "JJJJ-MM-DD",
        "mw-widgets-dateinput-placeholder-month": "JJJJ-MM",
+       "mw-widgets-mediasearch-noresults": "Geen resultaten gevonden.",
        "mw-widgets-titleinput-description-new-page": "pagina bestaat nog niet",
        "mw-widgets-titleinput-description-redirect": "doorverwijzing naar $1",
+       "mw-widgets-categoryselector-add-category-placeholder": "Voeg een categorie toe...",
        "sessionmanager-tie": "Het is niet mogelijk om meerdere authenticatietypen voor verzoeken te combineren: $1.",
        "sessionprovider-generic": "$1-sessies",
        "sessionprovider-mediawiki-session-cookiesessionprovider": "op cookies gebaseerde sessies",
        "log-action-filter-upload-overwrite": "Herupload",
        "authmanager-authn-autocreate-failed": "Het automatisch aanmaken van een lokaal account is mislukt: $1",
        "authmanager-create-disabled": "Het aanmaken van accounts is uitgeschakeld.",
+       "authmanager-authplugin-setpass-failed-title": "Wachtwoord wijzigen is mislukt",
+       "authmanager-userdoesnotexist": "Gebruikersaccount \"$1\" is niet geregistreerd.",
        "authmanager-email-label": "E-mail",
        "authmanager-email-help": "E-mailadres",
        "authmanager-realname-label": "Echte naam",
        "authmanager-provider-password": "Op wachtwoord gebaseerde authenticatie",
        "authmanager-provider-temporarypassword": "Tijdelijk wachtwoord",
        "authprovider-resetpass-skip-label": "Overslaan",
+       "authprovider-resetpass-skip-help": "Sla het resetten van het wachtwoord over.",
        "specialpage-securitylevel-not-allowed-title": "Niet toegestaan",
        "cannotauth-not-allowed-title": "Geen toegang",
        "changecredentials": "Authenticatiegegevens wijzigen",
        "linkaccounts-success-text": "Het account is gekoppeld.",
        "linkaccounts-submit": "Accounts koppelen",
        "unlinkaccounts": "Accounts ontkoppelen",
-       "unlinkaccounts-success": "Het account is ontkoppeld."
+       "unlinkaccounts-success": "Het account is ontkoppeld.",
+       "revid": "versie $1",
+       "pageid": "Pagina-ID $1"
 }
index 1f25b38..d2376a5 100644 (file)
        "passwordreset-emaildisabled": "ଏହି ଉଇକିରେ ଇମେଲ ସୁବିଧା ଅଚଳ କରାଯାଇଅଛି ।",
        "passwordreset-username": "ବ୍ୟବହାରକାରୀଙ୍କ ନାମ:",
        "passwordreset-domain": "ଡୋମେନ:",
-       "passwordreset-capture": "ଯାଉଥିବା ଇ-ମେଲଟି ଦେଖିବେ?",
-       "passwordreset-capture-help": "ଯଦି ଆପଣ ଘରଟିକୁ ଦେଖନ୍ତି ତେବେ (ଅସ୍ଥାୟୀ ପାସୱାର୍ଡ଼ ସହିତ) ଇ-ମେଲଟି ଆପଣଙ୍କୁ ଦେଖାଯିବ ଓ ବାକି ସଭ୍ୟମାନଙ୍କୁ ଚାଲିଯିବ ।",
        "passwordreset-email": "ଇ-ମେଲ ଠିକଣା:",
        "passwordreset-emailtitle": "{{SITENAME}} ର ଖାତା ସବିଶେଷ",
        "passwordreset-emailtext-ip": "କେହିଜଣେ (ବୋଧେ ଆପଣ, $1 IP addressରୁ) {{SITENAME}} ($4)ରେ ପାସୱାର୍ଡ଼ ରି-ସେଟ କରିବା ପାଇଁ ଅନୁରୋଧ କରିଛନ୍ତି । ଉକ୍ତ ଇମେଲ ଠିକଣା ସହିତ ଏହି {{PLURAL:$3|ସଭ୍ୟ ଖାତାଟି|ସଭ୍ୟ ଖାତାମାନ}} ସମ୍ବନ୍ଧିତ:\n\n$2\n\n{{PLURAL:$3|ଏହି ଅସ୍ଥାୟୀ ପାସୱାର୍ଡ଼ଟି|ଏହି ଅସ୍ଥାୟୀ ପାସୱାର୍ଡ଼ମାନ}} {{PLURAL:$5|ଦିନକ|$5 ଦିନ}}ରେ ଅଚଳ ହୋଇଯିବ ।\nଆପଣ ଏବେ ଲଗ ଇନ କରି ନୂଆ ପାସୱାର୍ଡ଼ଟିଏ ବାଛନ୍ତୁ । ଯଦି ଆଉ କେହି ଏହି ଅନୁରୋଧ କରିଥାନ୍ତି କିମ୍ବା ନିଜର ପୁରୁଣା ପାସୱାର୍ଡ଼ଟି ମନେପଡ଼ିଲା, ଏବଂ ଆଉ ପାସୱାର୍ଡ଼ଟି ବଦଳାଇବାକୁ ଚାହୁଁନାହାଁନ୍ତି ତାହେଲେ ଏହି ମେଲଟିକୁ ଅଣଦେଖା କରି ନିଜର ପୁରୁଣା ପାସୱାର୍ଡ଼ ବ୍ୟବହାର କରନ୍ତୁ ।",
        "userrights-reason": "କାରଣ:",
        "userrights-no-interwiki": "ଆପଣଙ୍କୁ ବାକି ଉଇକିରେ ସଭ୍ୟ ଅଧିକାର ବଦଳାଇବା ନିମନ୍ତେ ଅନୁମତି ମିଳିନାହିଁ ।",
        "userrights-nodatabase": "$1 ଡାଟାବେସଟି ନାହିଁ ବା କେବଳ ସ୍ଥାନୀୟ ହୋଇ ରହିଛି ।",
-       "userrights-nologin": "ଆପଣ ପରିଚାଳକ ଖାତାରୁ [[Special:UserLogin|ଲଗ ଇନ]] କରି ସଭ୍ୟ ଅଧିକାରର ସୁବିଧା ଦେଇପାରିବେ ।",
-       "userrights-notallowed": "ଆପଣଙ୍କ ଖାତାରେ ସଭ୍ୟ ଅଧିକାର ଯୋଡ଼ିବା ବା କାଢ଼ିବାର ଅନୁମତି ନାହିଁ ।",
        "userrights-changeable-col": "ଆପଣ ବଦଳାଇପାରିବା ଗୋଠସମୂହ",
        "userrights-unchangeable-col": "ଯେଉଁ ଗୋଠସବୁ ଆପଣ ବଦଳାଇପାରିବେ ନାହିଁ",
        "userrights-conflict": "ସଭ୍ୟଙ୍କ ଅଧିକାର ବଦଳାଇବାରେ ମତଭେଦ! କରିଥିବା ବଦଳକୁ ପରଖି ନିଶ୍ଚିତ କରନ୍ତୁ ।",
-       "userrights-removed-self": "ଆପଣ ସଫଳ ଭାବେ ନିଜର ଅଧିକାର କାଢ଼ିଦେଲେ । ଆଗକୁ ଆପଣ ଆଉ ଏହା ଦେଖିପାରିବେ ନାହିଁ ।",
        "group": "ଗୋଠ:",
        "group-user": "ବ୍ୟବହାରକାରୀଗଣ",
        "group-autoconfirmed": "ଆପେଆପେ ଥୟ କରା ସଭ୍ୟ",
        "right-siteadmin": "ଡାଟାବେସକୁ କିଳିବେ ଓ ଖୋଲିବେ",
        "right-override-export-depth": "୫ଟି ଯାଏଁ ଯୋଡ଼ାଯାଇଥିବା ପୃଷ୍ଠା ସହିତ ସବୁ ପୃଷ୍ଠାକୁ ରପ୍ତାନୀ କରିବେ",
        "right-sendemail": "ବାକି ସଭ୍ୟ ମାନଙ୍କୁ ଇ-ମେଲ ପଠାଇବେ",
-       "right-passwordreset": "ପାସୱାର୍ଡ଼ ପୁନସ୍ଥାପନ ଇମେଲ କରିବେ",
        "newuserlogpage": "ବ୍ୟବହାରକାରୀ ତିଆରି ଲଗ",
        "newuserlogpagetext": "ସଭ୍ୟଙ୍କର ଖାତା ଗଠନ ପାଇଁ ଏକ ଇତିହାସ ଅଛି ।",
        "rightslog": "ସଭ୍ୟଙ୍କ ଅଧିକାରର ଲଗ",
        "whatlinkshere": "ଏଠାରେ ଥିବା ଲିଙ୍କ",
        "whatlinkshere-title": "\"$1\" କୁ ପୃଷ୍ଠା ଲିଙ୍କ",
        "whatlinkshere-page": "ପୃଷ୍ଠା:",
-       "linkshere": "ଏହି ପୃଷ୍ଠା ସବୁ  <strong>[[:$1]]</strong> ସହ ଯୋଡା ଯାଇଅଛି:",
+       "linkshere": "à¬\8fହି à¬ªà­\83ଷà­\8dଠା à¬¸à¬¬à­\81  <strong>[[:$1]]</strong> à¬¸à¬¹ à¬¯à­\8bଡ଼ା à¬¯à¬¾à¬\87à¬\85à¬\9bି:",
        "nolinkshere": "'''[[:$1]]''' ସହିତ କୌଣସିଟି ପୃଷ୍ଠା ଯୋଡ଼ାଯାଇନାହିଁ ।",
        "nolinkshere-ns": "ବଛା ଯାଇଥିବା ନେମସ୍ପେସରେ '''[[:$1]]''' ନାଆଁ ସହ କୌଣସି ବି ପୃଷ୍ଠା ଯୋଡ଼ାଯାଇନାହିଁ ।",
        "isredirect": "ଆଉଥରେ ଫେରିବା ପୃଷ୍ଠା",
index 4197703..a89870c 100644 (file)
        "action-upload_by_url": "przesłania tego pliku z adresu URL",
        "action-writeapi": "zapisu poprzez interfejs API",
        "action-delete": "usunięcia tej strony",
-       "action-deleterevision": "usunięcia tej wersji",
-       "action-deletedhistory": "podglądu historii usunięć tej strony",
+       "action-deleterevision": "usuwania wersji",
+       "action-deletedhistory": "podglądu historii usunięć strony",
        "action-browsearchive": "przeszukiwania usuniętych stron",
-       "action-undelete": "odtworzenia tej strony",
-       "action-suppressrevision": "podglądu i odtworzenia tej wersji ukrytej",
+       "action-undelete": "odtwarzania stron",
+       "action-suppressrevision": "podglądu i odtwarzania ukrytych wersji",
        "action-suppressionlog": "podglądu rejestru ukrywania",
        "action-block": "zablokowania temu użytkownikowi możliwości edycji",
        "action-protect": "zmiany poziomu zabezpieczenia tej strony",
        "pageinfo-length": "Długość strony (w bajtach)",
        "pageinfo-article-id": "Identyfikator strony",
        "pageinfo-language": "Język zawartości strony",
+       "pageinfo-language-change": "zmień",
        "pageinfo-content-model": "Model zawartości",
        "pageinfo-content-model-change": "zmień",
        "pageinfo-robot-policy": "Indeksowanie przez roboty",
        "usercssispublic": "Uwaga: Podstrony z kodem CSS są widoczne publicznie i nie powinny zawierać poufnych danych.",
        "restrictionsfield-badip": "Nieprawidłowy adres IP lub zakres adresów: $1",
        "restrictionsfield-label": "Dozwolone zakresy adresów IP:",
-       "restrictionsfield-help": "Jeden adres IP lub zakres CIDR w wierszu. Aby zaznaczyć wszystkie, użyj<br><code>0.0.0.0/0</code><br><code>::/0</code>"
+       "restrictionsfield-help": "Jeden adres IP lub zakres CIDR w wierszu. Aby zaznaczyć wszystkie, użyj<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "wersja $1"
 }
index 368907c..58ef469 100644 (file)
        "tog-enotifminoredits": "Notificar-me por email também sobre edições menores de páginas ou arquivos",
        "tog-enotifrevealaddr": "Revelar meu endereço de email nas mensagens de notificação",
        "tog-shownumberswatching": "Mostrar o número de usuários que estão vigiando",
-       "tog-oldsig": "Sua Assinatura Existente:",
+       "tog-oldsig": "Assinatura atual:",
        "tog-fancysig": "Tratar assinatura como wikitexto (sem link automático)",
        "tog-uselivepreview": "Utilizar pré-visualização em tempo real",
        "tog-forceeditsummary": "Avisar-me ao introduzir um sumário de edição vazio",
        "talk": "Discussão",
        "views": "Visualizações",
        "toolbox": "Ferramentas",
-       "tool-link-userrights": "Editar grupos {{GENDER:$1|usuário}}",
+       "tool-link-userrights": "Editar grupos {{GENDER:$1|do usuário|da usuária|do(a) usuário(a)}}",
+       "tool-link-emailuser": "Enviar e-mail a {{GENDER:$1|este usuário|esta usuária|este(a) usuário(a)}}",
        "userpage": "Ver página de usuário",
        "projectpage": "Ver página de projeto",
        "imagepage": "Ver página do arquivo",
        "yourlanguage": "Língua:",
        "yourvariant": "Variante da língua de conteúdo:",
        "prefs-help-variant": "A sua variante preferida ou ortografia para mostrar no conteúdo das páginas deste wiki.",
-       "yournick": "Assinatura:",
+       "yournick": "Nova assinatura:",
        "prefs-help-signature": "Ao inserir comentários em páginas de discussão, assine-os colocando quatro tiles (<nowiki>~~~~</nowiki>) no fim dos comentários. Ao salvar, estes serão convertidos na sua assinatura mais a data e a hora da edição.",
        "badsig": "Assinatura inválida; verifique o código HTML utilizado.",
        "badsiglength": "A sua assinatura é muito longa.\nEla deve ter menos de $1 {{PLURAL:$1|caractere|caracteres}}.",
        "emailsubject": "Assunto:",
        "emailmessage": "Mensagem:",
        "emailsend": "Enviar",
-       "emailccme": "Enviar ao meu e-mail uma cópia de minha mensagem.",
+       "emailccme": "Enviar ao meu e-mail uma cópia de minha mensagem",
        "emailccsubject": "Cópia de sua mensagem para $1: $2",
        "emailsent": "E-mail enviado",
        "emailsenttext": "Sua mensagem foi enviada.",
        "deletepage": "Eliminar página",
        "confirm": "Confirmar",
        "excontent": "o conteúdo era: '$1'",
-       "excontentauthor": "o conteúdo era: \"$1\",e o único editor era \"[[Special:Contributions/$2|$2]]\" ([[User talk:$2|discussão]])",
+       "excontentauthor": "o conteúdo era: \"$1\", e {{GENDER:$2|o único editor|a única editora|o(a) único(a) editor(a)}} era [[Special:Contributions/$2|$2]] ([[User talk:$2|discussão]])",
        "exbeforeblank": "o conteúdo antes de esvaziar era: '$1'",
        "delete-confirm": "Eliminar \"$1\"",
        "delete-legend": "Eliminar",
        "actioncomplete": "Ação concluída",
        "actionfailed": "Falha na ação",
        "deletedtext": "\"$1\" foi eliminada.\nConsulte $2 para um registro de eliminações recentes.",
-       "dellogpage": "Registro de eliminação",
+       "dellogpage": "Registro de eliminações",
        "dellogpagetext": "Abaixo uma lista das eliminações mais recentes.",
        "deletionlog": "registro de eliminações",
        "reverted": "Revertido para versão anterior",
        "log-name-contentmodel": "Log de alterações do modelo de conteúdo",
        "logentry-contentmodel-change-revertlink": "reverter",
        "logentry-contentmodel-change-revert": "reverter",
-       "protectlogpage": "Registro de proteção",
+       "protectlogpage": "Registro de proteções",
        "protectlogtext": "Encontra-se abaixo o registro de proteção e desproteção de páginas.\nConsulte a [[Special:ProtectedPages|lista de páginas protegidas]] para ver as páginas que se encontram protegidas neste momento.",
        "protectedarticle": "protegeu \"[[$1]]\"",
        "modifiedarticleprotection": "alterou o nível de proteção para \"[[$1]]\"",
        "movepage-page-moved": "A página $1 foi movida para $2",
        "movepage-page-unmoved": "A página $1 não pôde ser movida para $2.",
        "movepage-max-pages": "O limite de $1 {{PLURAL:$1|página movida|páginas movidas}} foi atingido; não será possível mover mais páginas de forma automática.",
-       "movelogpage": "Registro de movimento",
+       "movelogpage": "Registro de movimentos",
        "movelogpagetext": "Abaixo encontra-se uma lista de páginas movidas.",
        "movesubpage": "{{PLURAL:$1|Subpágina|Subpáginas}}",
        "movesubpagetext": "Esta página tem $1 {{PLURAL:$1|subpágina mostrada|subpáginas mostradas}} abaixo.",
        "tooltip-feed-rss": "Feed RSS desta página",
        "tooltip-feed-atom": "Feed Atom desta página",
        "tooltip-t-contributions": "Ver as contribuições {{GENDER:$1|deste usuário|desta usuária|deste(a) usuário(a)}}",
-       "tooltip-t-emailuser": "Enviar um e-mail a {{GENDER:{{BASEPAGENAME}}|este usuário|esta usuária|este(a) usuário(a)}}",
+       "tooltip-t-emailuser": "Enviar um e-mail a {{GENDER:$1|este usuário|esta usuária|este(a) usuário(a)}}",
        "tooltip-t-info": "Mais informações sobre esta página",
        "tooltip-t-upload": "Enviar arquivos",
        "tooltip-t-specialpages": "Lista de páginas especiais",
        "ilsubmit": "Pesquisar",
        "bydate": "por data",
        "sp-newimages-showfrom": "Mostrar novos arquivos a partir das $2 de $1",
+       "seconds-abbrev": "$1&nbsp;s",
+       "minutes-abbrev": "$1&nbsp;min",
+       "hours-abbrev": "$1&nbsp;h",
        "seconds": "{{PLURAL:$1|um segundo|$1 segundos}}",
        "minutes": "{{PLURAL:$1|um minuto|$1 minutos}}",
        "hours": "{{PLURAL:$1|uma hora|$1 horas}}",
        "confirmrecreate": "O usuário [[User:$1|$1]] ([[User talk:$1|Discussão]]) eliminou esta página após você ter começado a editar, pelo seguinte motivo:\n: ''$2''\nPor favor, confirme que realmente deseja recriar esta página.",
        "confirmrecreate-noreason": "O usuário [[User:$1|$1]] ([[User talk:$1|discussão]]) eliminou esta página depois de você ter começado a editá-la. Confirme que deseja recriar a página, por favor.",
        "recreate": "Recriar",
+       "unit-pixel": "&nbsp;px",
        "confirm_purge_button": "OK",
        "confirm-purge-top": "Limpar a memória cache desta página?",
        "confirm-purge-bottom": "Purgar uma página limpa o ''cache'' e força a sua versão mais recente a aparecer.",
index 72d119e..3d2a954 100644 (file)
        "blockedtitle": "O utilizador está bloqueado",
        "blockedtext": "<strong>O seu nome de utilizador ou endereço IP foram bloqueados.</strong>\n\nO bloqueio foi realizado por $1.\nO motivo apresentado foi <em>$2</em>.\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\nNote que para utilizar a funcionalidade \"Contactar utilizador\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.",
        "autoblockedtext": "O seu endereço IP foi bloqueado de forma automática porque foi utilizado recentemente por outro utilizador, o qual foi bloqueado por $1.\nO motivo apresentado foi:\n\n:<em>$2</em>\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nPode contactar $1 ou outro [[{{MediaWiki:Grouppage-sysop}}|administrador]] para discutir o bloqueio.\n\nNote que para utilizar a funcionalidade \"Contactar utilizador\" precisa de ter um endereço de correio eletrónico válido nas suas [[Special:Preferences|preferências]] e de não lhe ter sido bloqueado o uso desta funcionalidade.\n\nO seu endereço IP neste momento é $3 e a identificação (ID) do bloqueio é #$5.\nInclua todos os detalhes acima em quaisquer contactos relacionados com este bloqueio, por favor.",
+       "systemblockedtext": "O seu nome de utilizador ou endereço IP foram bloqueados automaticamente pelo MediaWiki.\nO motivo fornecido é:\n\n:<em>$2</em>\n\n* Início do bloqueio: $8\n* Expiração do bloqueio: $6\n* Destinatário do bloqueio: $7\n\nO seu endereço IP atual é $3.\nInclua todos os detalhes acima em quaisquer contatos sobre este assunto, por favor.",
        "blockednoreason": "sem motivo especificado",
        "whitelistedittext": "Precisa de $1 para poder editar páginas.",
        "confirmedittext": "Precisa de confirmar o seu endereço de correio eletrónico antes de começar a editar páginas.\nIntroduza e valide o endereço através das [[Special:Preferences|preferências do utilizador]], por favor.",
        "emailsubject": "Assunto:",
        "emailmessage": "Mensagem:",
        "emailsend": "Enviar",
-       "emailccme": "Enviar uma cópia desta mensagem para o meu correio eletrónico.",
+       "emailccme": "Enviar uma cópia desta mensagem para o meu correio eletrónico",
        "emailccsubject": "Cópia da sua mensagem para $1: $2",
        "emailsent": "Mensagem enviada",
        "emailsenttext": "A sua mensagem foi enviada.",
        "deletepage": "Eliminar página",
        "confirm": "Confirmar",
        "excontent": "o conteúdo era: \"$1\"",
-       "excontentauthor": "o conteúdo era: \"$1\", e o único editor \"[[Special:Contributions/$2|$2]]\" ([[User talk:$2|talk]])",
+       "excontentauthor": "o conteúdo era: \"$1\", e {{GENDER:$2|o único editor|a única editora|o(a) único(a) editor(a)}} era [[Special:Contributions/$2|$2]] ([[User talk:$2|discussão]])",
        "exbeforeblank": "o conteúdo antes de esvaziar era: \"$1\"",
        "delete-confirm": "Eliminar \"$1\"",
        "delete-legend": "Eliminar",
        "pageinfo-length": "Tamanho da página (em bytes)",
        "pageinfo-article-id": "ID da página",
        "pageinfo-language": "Idioma do conteúdo da página",
+       "pageinfo-language-change": "alterar",
        "pageinfo-content-model": "Modelo de conteúdo de página",
        "pageinfo-content-model-change": "alterar",
        "pageinfo-robot-policy": "Indexação por robôs",
        "ilsubmit": "Pesquisar",
        "bydate": "por data",
        "sp-newimages-showfrom": "Mostrar novos ficheiros a partir das $2 de $1",
+       "seconds-abbrev": "$1&nbsp;s",
+       "minutes-abbrev": "$1&nbsp;min",
+       "hours-abbrev": "$1&nbsp;h",
        "seconds": "{{PLURAL:$1|um segundo|$1 segundos}}",
        "minutes": "{{PLURAL:$1|um minuto|$1 minutos}}",
        "hours": "{{PLURAL:$1|uma hora|$1 horas}}",
        "restrictionsfield-badip": "Endereço IP (ou gama de endereços IP) inválido: $1",
        "restrictionsfield-label": "Gamas de endereços IP permitidas:",
        "restrictionsfield-help": "Um endereço IP ou uma gama CIDR por linha. Para ativar todos,\nuse<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "revisão $1",
        "pageid": "identificador de página $1"
 }
index e4cfb10..e8037c6 100644 (file)
        "summary-preview": "Preview of the edit summary, shown under the edit summary itself.\nShould match: {{msg-mw|summary}}.",
        "subject-preview": "Should match {{msg-mw|subject}}",
        "previewerrortext": "When a user has the editing preference LivePreview enabled, clicked the Preview or Show Changes button in the edit page and the action did not succeed.",
-       "blockedtitle": "Used as title displayed for blocked users. The corresponding message body is one of the following messages:\n* {{msg-mw|Blockedtext|notext=1}}\n* {{msg-mw|Autoblockedtext|notext=1}}",
-       "blockedtext": "Text displayed to blocked users.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link)\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Autoblockedtext}}",
-       "autoblockedtext": "Text displayed to automatically blocked users.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block (in case of autoblocks: {{msg-mw|autoblocker}})\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link). Use it for GENDER.\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Blockedtext}}",
+       "blockedtitle": "Used as title displayed for blocked users. The corresponding message body is one of the following messages:\n* {{msg-mw|Blockedtext|notext=1}}\n* {{msg-mw|Autoblockedtext|notext=1}}\n* {{msg-mw|Systemblockedtext}}",
+       "blockedtext": "Text displayed to blocked users.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link)\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Autoblockedtext}}\n* {{msg-mw|Systemblockedtext}}",
+       "autoblockedtext": "Text displayed to automatically blocked users.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - the blocking sysop (with a link to his/her userpage)\n* $2 - the reason for the block (in case of autoblocks: {{msg-mw|autoblocker}})\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the blocking sysop's username (plain text, without the link). Use it for GENDER.\n* $5 - the unique numeric identifier of the applied autoblock\n* $6 - the expiry of the block\n* $7 - the intended target of the block (what the blocking user specified in the blocking form)\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Blockedtext}}\n* {{msg-mw|Systemblockedtext}}",
+       "systemblockedtext": "Text displayed to requests blocked by MediaWiki configuration.\n\n\"email this user\" should be consistent with {{msg-mw|Emailuser}}.\n\nParameters:\n* $1 - (Unused) A dummy user attributed as the blocker, possibly as a link to a user page.\n* $2 - the reason for the block\n* $3 - the current IP address of the blocked user\n* $4 - (Unused) the dummy blocking user's username (plain text, without the link).\n* $5 - A short string indicating the type of system block.\n* $6 - the expiry of the block\n* $7 - the intended target of the block\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Grouppage-sysop}}\n* {{msg-mw|Blockedtext}}\n* {{msg-mw|Autoblockedtext}}",
        "blockednoreason": "Substituted with <code>$2</code> in the following message if the reason is not given:\n* {{msg-mw|cantcreateaccount-text}}.\n{{Identical|No reason given}}",
        "whitelistedittext": "Used as error message. Parameters:\n* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description\nSee also:\n* {{msg-mw|Nocreatetext}}\n* {{msg-mw|Uploadnologintext}}\n* {{msg-mw|Loginreqpagetext}}",
        "confirmedittext": "Used as error message.",
        "booksources-search": "Search button in [[Special:BookSources]]\n\n{{Identical|Search}}",
        "booksources-text": "Used in [[Special:BookSources/1]].\n\nThis message is followed by a list of links to other sites.\n\nSee also:\n* {{msg-mw|Booksources|title}}\n* {{msg-mw|Booksources-text|text}}",
        "booksources-invalid-isbn": "This message is displayed after an invalid ISBN is entered on [[Special:Booksources]].",
-       "magiclink-tracking-rfc": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that use RFC magic links will be added.",
+       "magiclink-tracking-rfc": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that use RFC magic links will be added.\n\nSee [https://en.wikipedia.org/wiki/Help:Magic_links#RFC Help:Magic links] for more information on RFC magic links.",
        "magiclink-tracking-rfc-desc": "Description of the tracking category {{mw-msg|magiclink-tracking-rfc}}",
        "magiclink-tracking-pmid": "Name of the [[mw:Special:MyLanguage/Help:Tracking categories|tracking category]] where pages that use PMID magic links will be added.",
        "magiclink-tracking-pmid-desc": "Description of the tracking category {{mw-msg|magiclink-tracking-pmid}}",
        "emailccsubject": "Used in [[Special:EmailUser]].\n\nSubject of the carbon-copied email for the sender sent through MediaWiki.\n\nParameters:\n* $1 - target username\n* $2 - email subject",
        "emailsent": "Title of [[Special:EmailUser]] when it says you it sent an email",
        "emailsenttext": "Confirmation page: when you send an email, [[Special:EmailUser]] says you this (Your email has been sent).\n\nParameters:\n* $1 - (Optional) the recipient's username, for local customizations",
-       "emailuserfooter": "This message is appended to every email sent through the \"Email user\" function. Parameters:\n* $1 - username of the sender\n* $2 - username of the recipient",
+       "emailuserfooter": "This message is appended to every email sent through the \"Email user\" function. Parameters:\n* $1 - username of the sender\n* $2 - username of the recipient\n\n{{doc-singularthey}}",
        "usermessage-summary": "This message is used as an edit summary for any message that is posted because of a system event. Translate \"leaving a message\" in the sense of: to give a message to someone; to deliver a message somewhere; to deposit.",
        "usermessage-editor": "The user name for the user that is the editor of system messages. See [{{canonicalurl:Thread:Support/Message_info_please}} discussion on Support].",
        "usermessage-template": "{{optional}}",
        "removedwatchtext": "Message shown after clicking on the {{msg-mw|Unwatch}} tab in a content namespace page. Parameters:\n* $1 - page title\nSee also:\n* {{msg-mw|Addedwatchtext}}\n* {{msg-mw|Removedwatchtext-talk}}",
        "removedwatchtext-talk": "Message shown after clicking on the {{msg-mw|Unwatch}} tab in a talk namespace page. Parameters:\n* $1 - page title\nSee also:\n* {{msg-mw|Addedwatchtext-talk}}\n* {{msg-mw|Removedwatchtext}}",
        "removedwatchtext-short": "Explanation shown when unwatching item from [[Special:UnwatchedPages]].\n\nSee also:\n* {{msg-mw|Addedwatchtext-short}}.\n* {{msg-mw|Removedwatchtext}}.",
-       "watch": "{{doc-actionlink}}\nName of the Watch tab. Should be in the imperative mood.\n\nSee also:\n* {{msg-mw|Watch}}\n* {{msg-mw|Accesskey-ca-watch}}\n* {{msg-mw|Tooltip-ca-watch}}",
+       "watch": "{{doc-actionlink}}\nName of the Watch tab. Should be in the imperative mood.\n\nSee also:\n* {{msg-mw|Watch}}\n* {{msg-mw|Accesskey-ca-watch}}\n* {{msg-mw|Tooltip-ca-watch}}\n{{Identical|Watch}}",
        "watchthispage": "Used as link text.\n\nSee also:\n* {{msg-mw|Unwatchthispage|link text}}\n* {{msg-mw|Notanarticle|error message}}\n{{Identical|Watch this page}}",
        "unwatch": "{{doc-actionlink}}\nLabel of \"Unwatch\" tab.\n\nSee also:\n* {{msg-mw|Unwatch}}\n* {{msg-mw|Accesskey-ca-unwatch}}\n* {{msg-mw|Tooltip-ca-unwatch}}",
        "unwatchthispage": "Used as link text.\n\nSee also:\n* {{msg-mw|Watchthispage|link text}}\n* {{msg-mw|Notanarticle|error message}}",
        "wlshowhidemine": "Option text in [[Special:Watchlist]]. Cf. {{msg-mw|rcshowhidemine}}.",
        "wlshowhidecategorization": "Option text in [[Special:Watchlist]]. Cf. {{msg-mw|rcshowhidecategorization}}.",
        "watchlist-options": "Legend of the fieldset of [[Special:Watchlist]]\n\nSee also:\n* {{msg-mw|Watchlist-details|watchlist header}}\n* {{msg-mw|Wlheader-enotif|watchlist header}}\n* {{msg-mw|enotif reset|Submit button text}}",
-       "watchlist-mark-all-visited": "Dialog text in [[Special:Watchlist]] displayed for confirming whether the user wants to reset unseen watchlist changes by marking all pages as visited.",
        "watching": "Text displayed when clicked on the watch tab: {{msg-mw|Watch}}. It means the wiki is adding that page to your watchlist.",
        "unwatching": "Text displayed when clicked on the unwatch tab: {{msg-mw|Unwatch}}. It means the wiki is removing that page from your watchlist.",
        "watcherrortext": "When a user clicked the watch/unwatch tab and the action did not succeed, this message is displayed.\n\nThis message is used raw and should not contain wikitext.\n\nParameters:\n* $1 - ...\nSee also:\n* {{msg-mw|Addedwatchtext}}",
        "cant-move-to-user-page": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-category-page}}\n* {{msg-mw|cant-move-to-category-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
        "cant-move-category-page": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|cant-move-to-category-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
        "cant-move-to-category-page": "Used as error message.\n\nSee also:\n* {{msg-mw|cant-move-user-page}}\n* {{msg-mw|cant-move-to-user-page}}\n* {{msg-mw|cant-move-category-page}}\n* {{msg-mw|movenotallowedfile}}\n* {{msg-mw|movenotallowed}}\n* {{msg-mw|movenologintext}}",
+       "cant-move-subpages": "Used as an error message.",
+       "namespace-nosubpages": "Used as an error message. Parameters:\n* $1 - Namespace name.",
+       "movepage-max-pages": "Used as an error message. Parameters:\n* $1 - Maximum number of subpages allowed.",
        "newtitle": "Used in the special page \"[[Special:MovePage]]\". The text for the inputbox to give the new page title.\n\nSee also:\n* {{msg-mw|Move-page-legend|legend for the form}}\n* {{msg-mw|Movereason|label for textarea}}\n* {{msg-mw|Movetalk|label for checkbox}}\n* {{msg-mw|Move-leave-redirect|label for checkbox}}\n* {{msg-mw|Fix-double-redirects|label for checkbox}}\n* {{msg-mw|Move-subpages|label for checkbox}}\n* {{msg-mw|Move-talk-subpages|label for checkbox}}\n* {{msg-mw|Move-watch|label for checkbox}}",
        "move-watch": "The text of the checkbox to watch the pages you are moving from and to. If checked, both the destination page and the original page will be added to the watchlist, even if you decide not to leave a redirect behind.\n\nSee also:\n* {{msg-mw|Move-page-legend|legend for the form}}\n* {{msg-mw|newtitle|label for new title}}\n* {{msg-mw|Movereason|label for textarea}}\n* {{msg-mw|Movetalk|label for checkbox}}\n* {{msg-mw|Move-leave-redirect|label for checkbox}}\n* {{msg-mw|Fix-double-redirects|label for checkbox}}\n* {{msg-mw|Move-subpages|label for checkbox}}\n* {{msg-mw|Move-talk-subpages|label for checkbox}}",
        "movepagebtn": "Button label on the special 'Move page'.\n\n{{Identical|Move page}}",
        "pageinfo-length": "The length of the page, in bytes.",
        "pageinfo-article-id": "The numeric identifier of the page.\n{{Identical|Page ID}}",
        "pageinfo-language": "Language in which the page content is written.",
+       "pageinfo-language-change": "Link text for a link to Special:PageLanguage. The link will be wrapped in parenthesis.\n{{Identical|Change}}",
        "pageinfo-content-model": "The model in which the page content is written.\n\nUsed as label at [{{fullurl:Main Page|action=info}} action=info]. Followed by one of the following messages:\n* {{msg-mw|Content-model-wikitext}}\n* {{msg-mw|Content-model-javascript}}\n* {{msg-mw|Content-model-css}}\n* {{msg-mw|Content-model-text}}",
        "pageinfo-content-model-change": "Link text for a link to Special:ChangeContentModel. The link will be wrapped in parenthesis.\n{{Identical|Change}}",
        "pageinfo-robot-policy": "The search engine status of the page.\n\nUsed as label. Followed by any one of the following messages:\n*{{msg-mw|Pageinfo-robot-index}}\n*{{msg-mw|Pageinfo-robot-noindex}}",
        "restrictionsfield-badip": "An error message shown when one entered an invalid IP address or range in a restrictions field (such as Special:BotPassword). $1 is the IP address.",
        "restrictionsfield-label": "Field label shown for restriction fields (e.g. on Special:BotPassword).",
        "restrictionsfield-help": "Placeholder text displayed in restriction fields (e.g. on Special:BotPassword).",
-       "revid": "Used to format a revision ID number in text. Parameters:\n* $1 - Revision ID number.",
+       "revid": "Used to format a revision ID number in text. Parameters:\n* $1 - Revision ID number.\n{{Identical|Revision}}",
        "pageid": "Used to format a page ID number in text. Parameters:\n* $1 - Page ID number."
 }
index f6a017d..1e3a940 100644 (file)
        "htmlform-user-not-exists": "<strong>$1</strong> nu există.",
        "htmlform-user-not-valid": "<strong>$1</strong> nu este un nume de utilizator valid.",
        "logentry-delete-delete": "$1 {{GENDER:$2|a șters}} pagina $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|a șters}} pagina de redirecționare $3 prin suprascriere",
        "logentry-delete-restore": "$1 {{GENDER:$2|a restaurat}} pagina $3",
        "logentry-delete-event": "$1 {{GENDER:$2|a schimbat}} vizibilitatea {{PLURAL:$5|unui eveniment din jurnal|a $5 evenimente din jurnal|a $5 de evenimente din jurnal}} pentru $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|a schimbat}} vizibilitatea {{PLURAL:$5|unei versiuni|a $5 versiuni|a $5 de versiuni}} pentru pagina $3: $4",
index 1cacac4..ea3367c 100644 (file)
        "blockedtitle": "Участник заблокирован",
        "blockedtext": "'''Ваша учётная запись или IP-адрес заблокированы.'''\n\nБлокировка произведена администратором $1.\nУказана следующая причина: «''$2''».\n\n* Начало блокировки: $8\n* Окончание блокировки: $6\n* Цель блокировки: $7\n\nВы можете связаться с $1 или любым другим [[{{MediaWiki:Grouppage-sysop}}|администратором]], чтобы обсудить блокировку.\nОбратите внимание, что не сможете использовать функцию «письмо участнику», если в своих [[Special:Preferences|персональных настройках]] не задали или не подтвердили корректный адрес электронной почты, или если ваша блокировка включает запрет отправки писем подобным образом.\nВаш IP-адрес — $3, идентификатор блокировки — $5.\nПожалуйста, указывайте эти сведения в любых своих обращениях.",
        "autoblockedtext": "Ваш IP-адрес автоматически заблокирован в связи с тем, что он ранее использовался кем-то из участников, заблокированных {{GENDER:$4|участником|участницей}} $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, идентификатор блокировки — #$5.\nПожалуйста, указывайте эти сведения в любых своих обращениях.",
+       "systemblockedtext": "Ваше имя участника или IP-адрес были автоматически заблокированы MediaWiki.\nУказана следующая причина:\n\n:<em>$2</em>\n\n* Начало блокировки: $8\n* Окончание блокировки: $6\n* Цель блокировки: $7\n\nВаш текущий IP-адрес $3.\nПожалуйста, указывайте все эти сведения в любых своих обращениях.",
        "blockednoreason": "причина не указана",
        "whitelistedittext": "Вы должны $1 для изменения страниц.",
        "confirmedittext": "Вы должны подтвердить свой адрес электронной почты перед правкой страниц.\nПожалуйста, введите и подтвердите свой адрес электронной почты в своих [[Special:Preferences|персональных настройках]].",
        "pageinfo-length": "Длина страницы (в байтах)",
        "pageinfo-article-id": "Идентификатор страницы",
        "pageinfo-language": "Язык страницы",
+       "pageinfo-language-change": "изменить",
        "pageinfo-content-model": "Модель содержимого страницы",
        "pageinfo-content-model-change": "изменить",
        "pageinfo-robot-policy": "Индексация поисковыми роботами",
        "restrictionsfield-badip": "Недопустимый IP-адрес или диапазон адресов: $1",
        "restrictionsfield-label": "Разрешённые диапазоны IP-адресов:",
        "restrictionsfield-help": "По одному IP-адресу или CIDR-диапазону в строке. Чтобы разрешить всё, используйте <br /><code>0.0.0.0/0</code><br /><code>::/0</code>",
+       "revid": "версия $1",
        "pageid": "ID страницы $1"
 }
index b5706c5..9f62a74 100644 (file)
        "timezone-local": "Олохтоох",
        "duplicate-defaultsort": "Болҕой: Наардааһын «$2» күлүүһэ урукку «$1» күлүүһү сабар (Ключ сортировки переопределяет прежний ключ).",
        "duplicate-displaytitle": "<strong>Болҕой:</strong> Көрдөрүллүбүт «$2» аат урут көрдөрүллүбүт «$1» ааты уларытар.",
+       "restricted-displaytitle": "<strong>Болҕой:</strong> Суруллубут «$1» диэн аат ылыныллыбатах, тоҕо диэтэххэ сирэй билиҥҥи аатыгар сөп түбэспэт.",
        "invalid-indicator-name": "<strong>Алҕас:Сирэй туругун көрдөрөр индикатор </strong> атрибута <code>name</code> кураанах буолуо суохтаах.",
        "version": "MediaWiki барыла (биэрсийэтэ)",
        "version-extensions": "Туруоруллубут расширениялар",
        "version-libraries-description": "Ойуулааһын",
        "version-libraries-authors": "Ааптар",
        "redirect": "Билэттэн, кыттааччыттан, сирэйтэн эбэтэр барыл идентификаторыттан утаарыы",
-       "redirect-summary": "Бу аналлаах сирэй билэҕэ (билэ аатыттан), сирэйгэ (барыл эбэтэр сирэй идентификааторыттан) эбэтэр кыттааччы сирэйигэр (кыттааччы идентификаторыттан) утаарар. Туһаныы: \n[[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], \n[[{{#Special:Redirect}}/revision/328429]] эбэтэр\n[[{{#Special:Redirect}}/user/101]].",
+       "redirect-summary": "Бу аналлаах сирэй билэҕэ (билэ аатыттан), сирэйгэ (торум эбэтэр сирэй идентификаторыттан) эбэтэр кыттааччы сирэйигэр (кыттааччы идентификаторыттан) утаарар. Туһаныы: \n[[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/page/64308]], \n[[{{#Special:Redirect}}/revision/328429]],\n[[{{#Special:Redirect}}/user/101]] эбэтэр [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Толор",
        "redirect-lookup": "Көрдөт:",
        "redirect-value": "Суолтата:",
        "tag-filter-submit": "Фильтр",
        "tag-list-wrapper": "([[Special:Tags|{{PLURAL:$1|Тиэк|Тиэктэр}}]]: $2)",
        "tag-mw-contentmodelchange": "Иһинээҕи киэбин уларытыы сурунаала",
+       "tag-mw-contentmodelchange-description": "Сирэй [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ChangeContentModel ис тутулун уларытар] көннөрүүлэр",
        "tags-title": "Бэлиэлэр (тиэктэр)",
        "tags-intro": "Бу сирэйгэ бырагыраамма уларытыылары бэлиэтиир анал бэлиэлэрин (тиэктэрин) тиһиктэрэ уонна ол бэлиэлэр суолталара көстөр.",
        "tags-tag": "Бэлиэ (тиэк) аата",
        "tags-actions-header": "Дьайыылар",
        "tags-active-yes": "Сөп",
        "tags-active-no": "Суох",
-       "tags-source-extension": "Ð\9aÑ\8dÒ¥Ñ\8dÑ\82ииÑ\82инÑ\8dн Ð±Ñ\8bһааÑ\80Ñ\8bллаÑ\80",
+       "tags-source-extension": "ТÑ\83һанÑ\8bллаÑ\80 Ð±Ñ\8bÑ\80агÑ\8bÑ\80аамаÑ\82Ñ\82ан Ñ\82Ñ\83Ñ\82Ñ\83лÑ\83кÑ\82ааÑ\85",
        "tags-source-manual": "Кыттааччылар уонна буоттар киллэрэллэр",
        "tags-source-none": "Аны туттуллубат",
        "tags-edit": "уларытыы",
        "tags-deactivate": "араар",
        "tags-hitcount": "$1 {{PLURAL:$1|уларытыы|уларытыылар}}",
        "tags-manage-no-permission": "Тиэктэри уларытар кыаҕыҥ суох эбит.",
-       "tags-manage-blocked": "Хааччахтаммыт буолаҥҥын уларытыы бэлиэлэрин уларытар кыаҕыҥ суох.",
+       "tags-manage-blocked": "Хааччахтаммыт {{GENDER:$1|буолаҥҥын}} уларытыы тиэктэрин уларытар кыаҕыҥ суох.",
        "tags-create-heading": "Саҥа тиэги оҥоруу",
        "tags-create-explanation": "Саҥа оҥоһуллубут тиэктэри кыттааччылар уонна буоттар уларытар кыахтаах буолуохтара.",
        "tags-create-tag-name": "Бэлиэ аата:",
        "tags-delete-not-found": "Маннык $1 бэлиэ суох эбит.",
        "tags-delete-too-many-uses": "«$1» тиэк $2 торумтан ордукка туттуллар, ол аата сотуллар кыаҕа суох.",
        "tags-delete-warnings-after-delete": "«$1» тиэк сотулунна, ол эрээри {{PLURAL:$2|маннык сэрэтии|маннык сэрэтиилэр}} көһүннүлэр:",
+       "tags-delete-no-permission": "Тиэги уларыппыттарын көннөрөр кыаҕыҥ суох эбит.",
        "tags-activate-title": "Тиэги холбоо",
        "tags-activate-question": "\"$1\" тиэги холбоон эрэҕин.",
        "tags-activate-reason": "Төрүөтэ:",
        "tags-deactivate-not-allowed": "\"$1\" тиэги араарар табыллыбат.",
        "tags-deactivate-submit": "араар",
        "tags-apply-no-permission": "Бэйэҥ уларытыыгар уларытыы тиэгин туруорар кыаҕыҥ суох эбит.",
-       "tags-apply-blocked": "Хатана сылдьар кэмҥитигэр көннөрүүлэргитигэр уларытыы бэлиэлэрин туттаргыт табыллыбат.",
+       "tags-apply-blocked": "Хааччахтана сылдьар {{GENDER:$1|кэмҥэр}} көннөрүүлэриҥ тиэгин уларытарыҥ табыллыбат.",
        "tags-apply-not-allowed-one": "«$1» тиэги илииннэн туруорар табыллыбат эбит.",
        "tags-apply-not-allowed-multi": "Маннык {{PLURAL:$2|тиэк илиинэн угуллубат|тиэктэр илиинэн угуллубаттар}}: $1",
        "tags-update-no-permission": "Сурунаал тус-туспа торумнарын уонна суруктарын тиэгин эбэр уонна уларытар кыаҕыҥ суох эбит.",
-       "tags-update-blocked": "Хааччахтаммыт буолаҥҥыт уларытыы бэлиэлэрин уларытар кыаҕыҥ суох.",
+       "tags-update-blocked": "Хааччахтаммыт {{GENDER:$1|буолаҥҥын}} уларытыы тиэктэрин уларытар кыаҕыҥ суох.",
        "tags-update-add-not-allowed-one": "«$1» тиэги илииннэн туруорар табыллыбат эбит.",
        "tags-update-add-not-allowed-multi": "Маннык {{PLURAL:$2|тиэк илиинэн угуллубат|тиэктэр илиинэн угуллубаттар}}: $1",
        "tags-update-remove-not-allowed-one": "«$1» тиэги сотор табыллыбат эбит.",
        "tags-edit-revision-legend": "{{PLURAL:$1|Бу торумҥа|Бары $1 торумҥа}} тиэги угуу эбэтэр онтон сотуу",
        "tags-edit-logentry-legend": "Сурунаал {{PLURAL:$1|суругуттан|$1 бары суруктарыттан}} тиэги сот биитэр онно киллэр",
        "tags-edit-existing-tags": "Баар тиэктэр:",
-       "tags-edit-existing-tags-none": "''Суох''",
+       "tags-edit-existing-tags-none": "<em>Суох</em>",
        "tags-edit-new-tags": "Саҥа тиэктэр:",
        "tags-edit-add": "Бу тиэктэри эп:",
        "tags-edit-remove": "Бу тиэктэри сот:",
        "tags-edit-reason": "Төрүөтэ:",
        "tags-edit-revision-submit": "Уларытыылары бу {{PLURAL:$1|торумҥа|$1 торумнарга}} тарҕат",
        "tags-edit-logentry-submit": "Уларытыылары сурунаал бу {{PLURAL:$1|суругар|$1 суруктарыгар}} тарҕат",
-       "tags-edit-success": "Уларытыы сөпкө бигэргэннэ.",
+       "tags-edit-success": "Уларытыы бигэргэннэ.",
        "tags-edit-failure": "Уларытыылары туттар табыллыбата.\n$1",
        "tags-edit-nooldid-title": "Торум чопчу ыйыллыбата",
        "tags-edit-nooldid-text": "Ханнык торумҥа туттулларын талбатаххын, биитэр талбыт торумуҥ суох эбит.",
        "htmlform-cloner-create": "Өссө эп",
        "htmlform-cloner-delete": "Сот",
        "htmlform-cloner-required": "Саатар биирин толоруохтаах эбиккин.",
+       "htmlform-date-placeholder": "СССС-ЫЫ-КК",
+       "htmlform-time-placeholder": "ЧЧ:ММ:СС",
+       "htmlform-datetime-placeholder": "YYYY-MM-DD HH:MM:SS",
+       "htmlform-date-invalid": "Суруйбутуҥ күнү-дьылы бэлиэтээһиҥҥэ майгыннаабат. Маннык көрүҥү туһан: СССС-ЫЫ-КК.",
+       "htmlform-time-invalid": "Суруйбутуҥ кэми бэлиэтээһиҥҥэ майгыннаабат. Маннык көрүҥү туһан: ЧЧ-ММ-СС.",
+       "htmlform-datetime-invalid": "Суруйбутуҥ күнү-дьылы уонна кэми бэлиэтээһиҥҥэ майгыннаабат. Маннык көрүҥү туһан: СССС-ЫЫ-КК ЧЧ-ММ-СС.",
+       "htmlform-date-toolow": "Ыйбыт кэмиҥ муҥутуур кылгас кэмтэн кылгас эбит — $1.",
+       "htmlform-date-toohigh": "Ыйбыт кэмиҥ муҥутуур болдьохтон хойут эбит — $1.",
+       "htmlform-time-toolow": "Ыйбыт кэмиҥ болдьохтон кылгас — $1.",
+       "htmlform-time-toohigh": "Ыйбыт кэмиҥ болдьохтон уһун — $1.",
+       "htmlform-datetime-toolow": "Ыйбыт кэмиҥ анаммыт ыйтан-күнтэн уонна кэмтэн эрдэ буолан хаалбыт — $1.",
+       "htmlform-datetime-toohigh": "Ыйбыт кэмиҥ анаммыт күнтэн-дьылтан уонна кэмтэн хойут буолан хаалбыт — $1.",
        "htmlform-title-badnamespace": "[[:$1]] бу аат далыгар киирбэт эбит «{{ns:$2}}».",
        "htmlform-title-not-creatable": "«$1» оҥоһуллар сирэй аата буолбатах",
        "htmlform-title-not-exists": "$1 суох.",
        "htmlform-user-not-exists": "<strong>$1</strong> суох.",
        "htmlform-user-not-valid": "<strong>$1</strong> — маннык аат сатаммат.",
        "logentry-delete-delete": "$3 сирэйи $1 соппут",
+       "logentry-delete-delete_redir": "$1 кыттааччы $3 утаарыыны хос суруйуу көмөтүнэн {{GENDER:$2|соппут}}",
        "logentry-delete-restore": "$3 сирэйи $1 сөргүппүт",
        "logentry-delete-event": "Сурунаал $5 суругун көстүүтүн манна $3 $1 уларыппыт: $4",
        "logentry-delete-revision": "$3 сирэй $5 барылын көстүүтүн бу сирэйгэ $1 уларыппыт: $4",
        "logentry-suppress-block": "$1 маннык болдьоххо $5 $6 {{GENDER:$4|$3}} {{GENDER:$2|хааччаҕын суох гыммыт}}",
        "logentry-suppress-reblock": "$1 хааччах болдьоҕун {{GENDER:$4|$3}} манныкка $5 $6 {{GENDER:$2|уларыппыт}}",
        "logentry-import-upload": "$1 {{GENDER:$2|киллэрбит}} $3 билэни хачайдыыр ньыманнан",
+       "logentry-import-upload-details": "$1 билэ хачайдааһынынын көмөтүнэн $3 ($4 {{PLURAL:$4|торумун}}) {{GENDER:$2|иһирдьэ киллэрдэ}}",
        "logentry-import-interwiki": "$1 {{GENDER:$2|киллэрбит}} $3 атын биикиттэн",
+       "logentry-import-interwiki-details": "$1 кыттааччы $3 $5 торумуттан ($4 {{PLURAL:$4|торумун}}) {{GENDER:$2|иһирдьэ киллэрдэ}}",
        "logentry-merge-merge": "$1 {{GENDER:$2|холбообут}} мантан $3 манна $4 ($5 диэри торумнара)",
        "logentry-move-move": "$1 $3 сирэй аатын маннык $4 уларыппыт",
        "logentry-move-move-noredirect": "$3 сирэй аатын $1 маннык $4 уларыппыт, утаарыы-сирэй хаалларбатах",
        "logentry-protect-protect-cascade": "$1 {{GENDER:$2|көмүскээбит}} $3 $4 [каскаадынан]",
        "logentry-protect-modify": "$1 {{GENDER:$2|уларыппыт}}: $3 $4 көмүскэлин таһымын",
        "logentry-protect-modify-cascade": "$1 {{GENDER:$2|уларыппыт}}: $3 $4 көмүскэлин таһымын (каскаадынан)",
-       "logentry-rights-rights": "$3 бөлөхтөргө киириитин $1 уларыппыт: манныктан $4 манныкка $5",
+       "logentry-rights-rights": "$3 бөлөхтөргө киириитин $1 {{GENDER:$2|уларыппыт}}: мантан $4 манныкка $5",
        "logentry-rights-rights-legacy": "$3 бөлөхтөргө киириитин $1 уларыппыт",
        "logentry-rights-autopromote": "$1 мантан $4 манна $5 көһөрүллүбүт",
        "logentry-upload-upload": "$1 {{GENDER:$2|укпут}} $3",
        "logentry-managetags-deactivate": "$1 \"$4\" тиэги кыттааччылар уонна буоттар туһамматтарын курдук {{GENDER:$2|гыммыт}}",
        "log-name-tag": "Тиэк сурунаала",
        "log-description-tag": "Бу сирэй кыттааччылар [[Special:Tags|тиэктэри]] хаһан эппиттэрин биитэр соппуттарын көрдөрөр. Тиэги атын уларытыы, сотуу <strong>иһинэн</strong> оҥордоххо манна көстүбэт.",
+       "logentry-tag-update-add-revision": "$6 {{PLURAL:$7|тиэги}} $3 сирэй $4 торумугар $1 {{GENDER:$2|эппит}}",
+       "logentry-tag-update-add-logentry": "$6 {{PLURAL:$7|тиэги}} $5 сурунаал $3 сирэйигэр $6  торумугар $1 {{GENDER:$2|эппит}}",
+       "logentry-tag-update-remove-revision": "$1 $3 сирэй $4 торумуттан $8 {{PLURAL:$9|тиэги}} {{GENDER:$2|соппут}}",
+       "logentry-tag-update-remove-logentry": "$1  $8 {{PLURAL:$9|тиэги}} $5 сурунаал $3 сирэйиттэн {{GENDER:$2|соппут}}",
        "rightsnone": "(суох)",
        "revdelete-summary": "уларытыылар туһунан",
        "feedback-adding": "Сирэй туһунан санаа этии...",
        "feedback-useragent": "Браузерым:",
        "searchsuggest-search": "{{SITENAME}} иһигэр көрдөөһүн",
        "searchsuggest-containing": "тыл баар ыстатыйалара...",
+       "api-error-autoblocked": "Эн IP-аадырыһыҥ бүөлэммит кыттааччы туттубутун иһин хааччахтаммыт.",
        "api-error-badaccess-groups": "Эн бу биикигэ билэ киллэрэриҥ хааччахтаммыт.",
        "api-error-badtoken": "Ис алҕас: Омсолоох токен.",
+       "api-error-blocked": "Уларытар кыаххын быспыттар эбит.",
        "api-error-copyuploaddisabled": "URL көмөтүнэн киллэрии бу сиэрбэргэ араарыллыбыт.",
        "api-error-duplicate": "Маннык иһинээҕилээх {{PLURAL:$1|атын билэ баар эбит}}",
        "api-error-duplicate-archive": "Урут ситим-сиргэ маннык иһинээҕилээх {{PLURAL:$1|билэ баар|билэлэр бааллар}} этэ, ол гынан баран {{PLURAL:$1|сотуллубута|сотуллубуттара}}.",
        "api-error-nomodule": "Ис алҕас: хачайдыыр муодул туруоруута суох.",
        "api-error-ok-but-empty": "Ис алҕас: сиэрбэртэн хоруй кэлбэтэ.",
        "api-error-overwrite": "Баар билэни уларытар сатаммат.",
+       "api-error-ratelimited": "Наһаа элбэх билэни кылгас кэм иһигэр уга сатаатыҥ.\nТохтуу түһэн баран хатылаан көрөөр.",
        "api-error-stashfailed": "Ис алҕас: сиэрбэр быстах кэмҥэ оҥоһуллубут билэни кыайан бигэргэппэтэх.",
        "api-error-publishfailed": "Ис алҕас: сиэрбэр быстах билэни кыайан бигэргэппэтэх.",
        "api-error-stasherror": "Билэни угарга алҕас таҕыста.",
        "api-error-unknownerror": "Биллибэт алҕас: $1",
        "api-error-uploaddisabled": "Бу биикигэ хачайдыыр араарыллыбыт эбит.",
        "api-error-verification-error": "Бу билэ алдьаммыт эбэтэр табыгаһа суох кэҥэтиилээх.",
+       "api-error-was-deleted": "Маннык ааттаах билэ урут баар буола сылдьыбыт, онтон сотуллубут эбит.",
        "duration-seconds": "$1 сөкүүндэ",
        "duration-minutes": "$1 мүнүүтэ",
        "duration-hours": "$1 чаас",
        "expand_templates_generate_rawhtml": "HTML-ы көрдөр",
        "expand_templates_preview": "Холоон көрүү",
        "expand_templates_preview_fail_html": "<em>raw HTML холбоно сылдьар {{SITENAME}} ситим-сир сиэссийэтин сүтэрэн кэбиспит буолан, эрдэ көрүү сатаммат, бу JavaScript-атаакаттан көмүскэнэр ньыма.</em>\n\n<strong>Эрдэ көрөрүҥ буортуну аҕалбат буоллаҕына хатылаан көр.</strong>\nСин биир сатамматаҕына [[Special:UserLogout|үлэҕин түмүктээ]] уонна хат киирэн көр.",
+       "expand_templates_preview_fail_html_anon": "<em>{{SITENAME}} ситим-сиргэ «сиикэй» HTML холбоммут буолан уонна эн ааккын эппэтэх буолаҥҥын эрдэ көрүү сатаммат, бу JavaScript-атаакаттан көмүскэнии.</em>\n\n<strong>Өскөтүн туох да куһаҕаны оҥоруоххун баҕарбат буоллаххына, [[Special:UserLogin|киир]] уонна хатылаа.",
        "expand_templates_input_missing": "Эһиги ханнык эмит тиэкиһи туруор.",
-       "pagelanguage": "СиÑ\80Ñ\8dй Ñ\82Ñ\8bлÑ\8bн Ñ\82алыы",
+       "pagelanguage": "СиÑ\80Ñ\8dй Ñ\82Ñ\8bлÑ\8bн Ñ\83лаÑ\80Ñ\8bÑ\82ыы",
        "pagelang-name": "Сирэй",
        "pagelang-language": "Омугун тыла",
        "pagelang-use-default": "Сүрүн тылы тутун",
        "action-pagelang": "сирэй тылын уларытар буол",
        "log-name-pagelang": "Тылы уларытыы сурунаала",
        "log-description-pagelang": "Сирэй тылын талыы сурунаала.",
-       "logentry-pagelang-pagelang": "$1 ÐºÑ\8bÑ\82Ñ\82ааÑ\87Ñ\87Ñ\8b $3 Ñ\81иÑ\80Ñ\8dй Ñ\82Ñ\8bлÑ\8bн мантан $4 манныкка $5 {{GENDER:$2|уларыппыт}}.",
+       "logentry-pagelang-pagelang": "$1 ÐºÑ\8bÑ\82Ñ\82ааÑ\87Ñ\87Ñ\8b $3 Ñ\82Ñ\8bлÑ\8b мантан $4 манныкка $5 {{GENDER:$2|уларыппыт}}.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (холбоммут)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>арахсыбыт</strong>)",
        "mediastatistics": "Миэдьийэ ыстатыыстыката",
        "special-characters-group-ipa": "МФА (IPA)",
        "special-characters-group-symbols": "Бэлиэлэр",
        "special-characters-group-greek": "Гириэктии",
+       "special-characters-group-greekextended": "Кэҥэтиллибит гириэк",
        "special-characters-group-cyrillic": "Кириллица",
        "special-characters-group-arabic": "Араабтыы",
        "special-characters-group-arabicextended": "Араабтыы кэҥэтиллибит",
        "special-characters-title-emdash": "уһун тире",
        "special-characters-title-minus": "минус бэлиэтэ",
        "mw-widgets-dateinput-no-date": "Күнэ-дьыла ыйыллыбатах",
+       "mw-widgets-mediasearch-input-placeholder": "Миэдьийэ билэлэри көрдөөһүн",
+       "mw-widgets-mediasearch-noresults": "Туох да көстүбэтэ.",
        "mw-widgets-titleinput-description-new-page": "сирэй суох эбит",
        "mw-widgets-titleinput-description-redirect": "манна $1 утаарыы",
-       "randomrootpage": "Түбэһиэх төрүт сирэй."
+       "mw-widgets-categoryselector-add-category-placeholder": "Категория эбии...",
+       "sessionmanager-tie": "Тургутуу хас да көрүҥүн биирдэ туһанар сатаммат: $1.",
+       "sessionprovider-generic": "$1 сиэссийэ",
+       "sessionprovider-mediawiki-session-cookiesessionprovider": "куукаҕа олоҕурбут сиэссийэ",
+       "sessionprovider-nocookies": "Куука арахсыбыт буолуон сөп. оннук түгэҥҥэ холбоон баран хатылаа.",
+       "randomrootpage": "Түбэһиэх төрүт сирэй.",
+       "log-action-filter-block": "Хааччах көрүҥэ:",
+       "log-action-filter-delete": "Сотуу көрүҥэ:",
+       "log-action-filter-import": "Киллэрии көрүҥэ:",
+       "log-action-filter-all": "Бары",
+       "log-action-filter-block-block": "Бобуу",
+       "log-action-filter-block-reblock": "Бобууну уларытыы",
+       "log-action-filter-block-unblock": "Бобууну суох гыныы",
+       "log-action-filter-contentmodel-change": "Иһинээҕитин мадьыалын уларытыы",
+       "log-action-filter-contentmodel-new": "Contentmodel диэн мадьыалынан сирэйи айыы",
+       "log-action-filter-delete-delete": "Сирэйи сотуу",
+       "log-action-filter-delete-delete_redir": "Утаарыыны хат суруйуу",
+       "log-action-filter-delete-restore": "Сирэйи сөргүтүү",
+       "log-action-filter-delete-event": "Сурунаалы сотуу",
+       "log-action-filter-delete-revision": "Торуму сотуу",
+       "log-action-filter-import-interwiki": "Трансвики импорт",
+       "log-action-filter-import-upload": "XML-ынан киллэрии",
+       "log-action-filter-managetags-create": "Тиэктэри оҥоруу",
+       "log-action-filter-managetags-delete": "Тиэги сотуу",
+       "log-action-filter-managetags-activate": "Тиээги холбооһун",
+       "log-action-filter-managetags-deactivate": "Тиэги араарыы",
+       "log-action-filter-move-move": "Утаарыыны хас суруйбакка салгыы барыы",
+       "log-action-filter-move-move_redir": "Утаарыыны солбуйан сыҕарытыы",
+       "log-action-filter-newusers-create": "Аатын эппэтэх кыттааччы оҥоруута",
+       "log-action-filter-newusers-create2": "Бэлиэтэммит кыттааччы оҥоруута",
+       "log-action-filter-newusers-autocreate": "Аптамаатынан оҥоруу",
+       "log-action-filter-newusers-byemail": "Почтанан кэлбит аһарыгы туһанан оҥоруу",
+       "log-action-filter-patrol-patrol": "Киһи ботурууллааһына",
+       "log-action-filter-patrol-autopatrol": "Аптамаат ботурууллааһына",
+       "log-action-filter-protect-protect": "Көмүскэл",
+       "log-action-filter-protect-modify": "Көмүскэли уларытыы",
+       "log-action-filter-protect-unprotect": "Көмүскэли суох гыныы",
+       "log-action-filter-protect-move_prot": "Көмүскэли көһөрүү",
+       "log-action-filter-rights-rights": "Киһи уларытыыта",
+       "log-action-filter-rights-autopromote": "Аптамаат уларытыыта",
+       "log-action-filter-suppress-event": "Сурунаалы кистээһин",
+       "log-action-filter-suppress-revision": "Торуму кистээһин",
+       "log-action-filter-suppress-delete": "Сирэйи кистээһин",
+       "log-action-filter-suppress-block": "Кыттааччыны бобуу көмөтүнэн кистээһин",
+       "log-action-filter-suppress-reblock": "Кыттааччыны хос бобуу көмөтүнэн кистээһин",
+       "log-action-filter-upload-upload": "Саҥа хачайдаан киллэрии",
+       "log-action-filter-upload-overwrite": "Хат ыытыы"
 }
index 7196cfc..037258d 100644 (file)
        "views": "ڏيٺون",
        "toolbox": "اوزارَ",
        "tool-link-userrights": "{{GENDER:$1|يوزر}} گروھ تبديل ڪريو",
+       "tool-link-userrights-readonly": "{{GENDER:$1|يوزر}} گروھ ڏسو",
        "tool-link-emailuser": "ھن {{GENDER:$1|يوزر}} ڏانھن برقٽپال موڪليو",
        "userpage": "يوزر صفحو ڏسو",
        "projectpage": "رٿائي صفحو ڏسو",
        "jumptosearch": "ڳولا",
        "view-pool-error": "معذرت سان سرور هاڻي تمام گھڻو سُڪ آهي.\nتمام گھڻا يوزر ھن صفحي کي ڏسڻ جي ڪوشش ڪري رھيا آھن.\nمهرباني ڪري ٿورو ترسو انکان اڳ جو توھان ھن صفحي تائين رسڻ لاءِ ٻيھر ڪوشش ڪريو.\n\n$1",
        "generic-pool-error": "معذرت سان سرور هاڻي تمام گھڻو سُڪ آهي.\nتمام گھڻا يوزر هتي موجود آهن.\nمهرباني ڪري ٿورو ترسي پوءِ ڪوشش ڪريو.",
-       "pool-errorunknown": "اڻ ڄاتل چُڪَ",
+       "pool-errorunknown": "اڻڄاتل چُڪَ",
        "poolcounter-usage-error": "استعمال جي خرابي: $1",
        "aboutsite": "{{SITENAME}} بابت",
        "aboutpage": "Project:بابت",
        "mycustomcssprotected": "توهان کي هيءُ CSS صفحو سنوارڻ جي اجازت نہ آهي.",
        "mycustomjsprotected": "توهان کي هيءُ جاوا اسڪرپٽ صفحو سنوارڻ جي اجازت حاصل ڪانهي.",
        "myprivateinfoprotected": "توهان کي پنهنجي ذاتي معلومات سنوارڻ جي اجازت حاصل نہ آهي.",
-       "mypreferencesprotected": "توهان جي پنهنجون ترجيحات سنوارڻ جي اجات حاصل ڪانهي.",
+       "mypreferencesprotected": "توھان کي پنھنجون ترجيحون سنوارڻ جي اجات حاصل ڪانھي.",
        "ns-specialprotected": "خاص صفحا سنواري نٿا سگھجن.",
        "titleprotected": "[[User:$1|$1]] اهڙي عنوان سان صفحو سرجڻ تي روڪ لڳائي ڇڏي آهي. سبب <em>$2</em> ڄاڻايو ويو آهي.",
        "exception-nologin": "داخل ٿيل نہ آهيو",
-       "virus-unknownscanner": "اڻ ڄاتل نِس وائرس:",
+       "virus-unknownscanner": "اڻڄاتل نِس وائرس:",
        "cannotlogoutnow-title": "ھاڻي خارج نٿو ٿي سگھجي",
-       "cannotlogoutnow-text": "$1 استعمال ڪرڻ دوران ٻاھر نڪرڻ ممڪن نہ آھي.",
+       "cannotlogoutnow-text": "$1 استعمال ڪرڻ دوران خارج ٿيڻ ممڪن نہ آھي.",
        "welcomeuser": "ڀلي ڪري آيا، $1!",
        "yourname": "يُوزرنانءُ:",
        "userlogin-yourname": "يوزرنانءُ",
        "nav-login-createaccount": "داخل ٿيو / کاتو کوليو",
        "userlogin": "داخل ٿيو / کاتو کوليو",
        "userloginnocreate": "داخل ٿيو",
-       "logout": "ٻاھر نڪرو",
-       "userlogout": "ٻاھر نڪرو",
+       "logout": "خارج ٿيو",
+       "userlogout": "خارج ٿيو",
        "notloggedin": "داخل ٿيل نہ آهيو",
        "userlogin-noaccount": "کاتو نہ ٿا رکو؟",
        "userlogin-joinproject": "{{SITENAME}} ۾ شامل ٿيو",
        "createacct-error": "کاتو کولڻ ۾ چُڪَ",
        "createaccounterror": "کاتو کُلي نہ سگھيو: $1",
        "nocookiesnew": "يُوزر کاتو کلي چڪو، پر توهان داخل نہ ٿيا آهيو. يُوزرس کي داخل ڪرڻ لاءِ {{SITENAME}} ڪوڪيز استعمال ڪندي آهي. توهان ڪوڪيز کي ناڪاره بڻائي رکيو آهي. داخل ٿيڻ لاءِ ڪوڪيز کي ڪارائتو بڻايو.",
-       "nocookieslogin": "يُوزرس کي لاگ اِن ڪرڻ لاءِ {{SITENAME}} ڪوڪيز استعمال ڪندي آهي. توهان ڪوڪيز کي ناڪاره بڻائي رکيو آهي. لاگ اِن ٿيڻ لاءِ ڪوڪيز کي ڪارائتو بڻايو.",
+       "nocookieslogin": "يُوزرس کي داخل ڪرڻ لاءِ {{SITENAME}} ڪوڪيز استعمال ڪندي آهي.\nتوھان ڪوڪيز کي ناڪاره بڻائي رکيو آھي.\nداخل ٿيڻ لاءِ ڪوڪيز کي ڪارائتو بڻايو.",
        "noname": "توهان جو ڄاڻايل يُوزرنانءُ ناقابل ڪار آهي.",
        "loginsuccesstitle": "داخل ٿيل",
        "loginsuccess": "'''هاڻي توهان {{SITENAME}} تي بطور \"$1\" داخل ٿيل آهيو.'''",
        "password-name-match": "توهان جو ڳجھولفظ توهان جي يوزرنانءُ کان مختلف هجڻ گھرجي.",
        "mailmypassword": "ڳجھولفظ ٻيھر مقرر ڪريو",
        "passwordremindertitle": "{{SITENAME}} لاءِ نئون عارضي ڳجھولفظ",
-       "passwordremindertext": "ڪنهن (شايد توهان آءِ پي پتي $1 تان) اسان کي {{SITENAME}} ($4) لاءِ نئون ڳجھو لفظ اماڻڻ جي گھُرَ ڪئي.\"$2\" يوزر لاءِ هڪ ڳجھُ لفظ تخليق ڪيو ويو آهي \"$3\" تي ترتيب ڏنو ويو هو. جيڪڏهن اهو توهان جي ارادو هيو، ته هاڻي توهان کي هينئر ئي لاگ اِن ٿي پنهنجو ڳجھو لفظ تبديل ڪرڻ گھرجي.\nتوهان جو عارضي ڳجھو لفظ {{PLURAL:$5|هڪ ڏينهُن|$5 ڏينهَن}} ۾ ختم ٿيندو.\n\nجيڪڏهن اها گھُرَ اوهان نه ڪئي هئي، يا هاڻي اوهان کي پنهنجو ڳجھو لفظ ياد اچي ويو آهي ۽ توهان ان کي تبديل ڪرڻ نه ٿا چاهيو، ته توهان هن نياپي کي نظر انداز ڪندي پنهنجو پراڻو ڳجھو لفظ ئي استعمال ڪري سگھو ٿا.",
+       "passwordremindertext": "ڪنھن (شايد توھان آءِپي پتي $1 تان) اسان کي {{SITENAME}} ($4) لاءِ نئون ڳجھولفظ اماڻڻ جي گُھرَ ڪئي.\"$2\" يوزر لاءِ ھڪ ڳجھولفظ تخليق ڪيو ويو آهي \"$3\" تي ترتيب ڏنو ويو ھو. جيڪڏھن اھو توھان جو ارادو ھيو، تہ ھاڻي توھان کي ھينئر ئي داخل ٿي پنھنجو ڳجھولفظ تبديل ڪرڻ گھرجي.\nتوھان جو عارضي ڳجھولفظ {{PLURAL:$5|هڪ ڏينھُن|$5 ڏينھَن}} ۾ ختم ٿيندو.\n\nجيڪڏھن اھا گُھرَ اوھان نہ ڪئي ھئي، يا ھاڻي اوھان کي پنھنجو ڳجھولفظ ياد اچي ويو آھي ۽ توھان ان کي تبديل ڪرڻ نٿا چاھيو، تہ توھان ھن نياپي کي نظر انداز ڪندي پنھنجو پراڻو ڳجھولفظ ئي استعمال ڪري سگھو ٿا.",
        "noemail": "يُوزر \"$1\" جي ڪو بہ برقٽپال پتو درج ٿيل ناهي.",
        "noemailcreate": "توھان کي قابلڪار برقٽپال پتو مھيا ڪرڻو پوندو.",
        "passwordsent": "يوزر \"$1\" لاءِ ھڪ نئون ڳجھولفظ برقٽپال ذريعي اماڻيو ويو آهي.  مھرباني ڪري اھو حاصل ڪرڻ بعد داخل ٿيندا.",
        "pt-login-button": "داخل ٿيو",
        "pt-login-continue-button": "داخل ٿيڻ جاري رکو",
        "pt-createaccount": "کاتو کوليو",
-       "pt-userlogout": "ٻاھر نڪرو",
+       "pt-userlogout": "خارج ٿيو",
        "php-mail-error-unknown": "پي ايڇ پي جي  ڪاڄ اندر اڻڄاتل چُڪَ.",
-       "user-mail-no-addy": "برق ٽپال پتو ڄاڻائڻ کان سواءِ برق ٽپال اماڻڻ جي ڪوشش ڪئي وئي.",
+       "user-mail-no-addy": "برقٽپال پتو ڄاڻائڻ کان سواءِ برق ٽپال اماڻڻ جي ڪوشش ڪئي وئي.",
        "changepassword": "ڳجھولفظ تبديل ڪريو",
        "resetpass_announce": "داخل ٿيڻ جو عمل پورو ڪرڻ لاءِ، توهان کي نئون ڳجھولفظ اختيار مقرر ڪرڻو پوندو.",
        "resetpass_header": "کاتي جو ڳجھولفظ بدلايو",
        "resetpass_submit": "ڳجھولفظ طَي ڪريو ۽ داخل ٿيو",
        "changepassword-success": "توهان جو ڳجھولفظ بدلايو ويو آھي!",
        "changepassword-throttled": "توهان تازو ئي داخل ٿيڻ جون هيڪانديون گھڻيون ڪوششون ڪيون آهن. مهرباني ڪري $1 لاءِ ترسي پوءِ وري ڪوشش ڪريو.",
+       "botpasswords": "بوٽ جو ڳجھولفظ",
+       "botpasswords-disabled": "بوٽ ڳجھالفظ ناقابلِڪار ڪيل آھن.",
        "botpasswords-label-create": "سرجيو",
        "botpasswords-label-update": "تجديد",
        "botpasswords-label-cancel": "رد",
        "resetpass-submit-cancel": "رد",
        "resetpass-wrong-oldpass": "ناقابل ڪار هاڻوڪو يا عارضي ڳجھولفظ. \nتوهان پنهنجو ڳجھو لفظ اڳ ۾ ئي بدلائي چڪا آهيو يا نئين ڳجھي لفظ لاءِ درخواست ڏئي چڪا آهيو.",
        "resetpass-recycled": "مهرباني ڪري پنهنجي هاڻوڪي ڳجھي لفظ کان ڪو مختلف ڳجھو لفظ چونڊيو.",
-       "resetpass-temp-emailed": "توهان برق ٽپال ذريعي اماڻيل عارضي ڳجھي لفظ سان لاگ اِن ٿيا آهيو. لاگ اِن کي مڪمل ڪرڻ لاءِ توهان کي هتي نئون ڳجھو لفظ طَي ڪرڻو ئي پوندو:",
+       "resetpass-temp-emailed": "توهان برقٽپال ذريعي اماڻيل عارضي ڳجھي لفظ سان داخل ٿيا آهيو. داخل ٿيڻ کي مڪمل ڪرڻ لاءِ توهان کي هتي نئون ڳجھولفظ طَي ڪرڻو ئي پوندو:",
        "resetpass-temp-password": "عارضي ڳجھولفظ:",
        "resetpass-expired": "توهان جو ڳجھولفظ مدي خارج ٿي چڪو آهي. نئون ڳجھولفظ مقرر ڪريو ۽ داخل ٿيو.",
        "resetpass-expired-soft": "توهان جو ڳجھو لفظ مدي خارج ٿي چڪو آهي. مهرباني ڪري نئون ڳجھو لفظ چونڊيو، يا ساڳيو ڪم ڪنهن ٻي وقت ڪرڻ لاءِ \"{{int:authprovider-resetpass-skip-label}}\" تي ڪلڪ ڪريو.",
        "summary-preview": "تت تي پيش نگاھ:",
        "subject-preview": "موضوع پيش نگاھ:",
        "blockedtitle": "يُوزر بندشيل آهي.",
-       "blockedtext": "'''توهان جي يوزرنانءُ يا آءِ پي کي بندشيو ويو آهي.'''\n\nبندش $1 هنئي. جڏهن تہ ڄاڻايل سبب ''$2'' آهي.\n\n\n* بندش جو آغاز: $8\n* بندش جو انجام: $6\n* بندش جو هدف: $7\n\nاهڙي روڪ تي بحث ڪرڻ لاءِ توهان $1 يا ڪنهن ٻي [[{{MediaWiki:Grouppage-sysop}}|منتظم]] سان رابطو ڪري سگھو ٿا. جيڪڏهن توهان جو درست [[Special:ترجيحات|کاتو ترجيحات]] ۾ درست برق ٽپال پتو درج ٿيل نہ آهي تہ توهان 'هن يوزر کي برق ٽپال ڪريو' وارو فيچر نہ ٿا \nYou cannot use the 'e-mail this user' feature unless a valid e-mail address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nاستعمال ڪري سگھو. توهان جو هاڻوڪو آءِ پي پتو $3 آهي، ۽ بندش سڃاڻپ $5 آهي. مهرباني ڪري ڪنهن بہ پڇا ڳاڇا يا لهوچڙ لاءِ انهن مان ڪنهن هڪ يا ٻنهي جو حوالو ڏيندا.",
+       "blockedtext": "'''توھان جي يوزرنانءُ يا آءِ پي کي بندشيو ويو آھي.'''\n\nبندش $1 ھني. جڏھن تہ ڄاڻايل سبب ''$2'' آهي.\n\n\n* بندش جو آغاز: $8\n* بندش جو انجام: $6\n* بندش جو هدف: $7\n\nاھڙي روڪ تي بحث ڪرڻ لاءِ توھان $1 يا ڪنھن ٻي [[{{MediaWiki:Grouppage-sysop}}|منتظم]] سان رابطو ڪري سگھو ٿا. جيڪڏهن توھان جو درست [[Special:ترجيحون|کاتو ترجيحون]] ۾ درست برقٽپال پتو درج ٿيل نہ آهي تہ توهان 'هن يوزر کي برقٽپال ڪريو' وارو فيچر نہ ٿا \nYou cannot use the 'e-mail this user' feature unless a valid e-mail address is specified in your [[Special:Preferences|account preferences]] and you have not been blocked from using it.\nاستعمال ڪري سگھو. توھان جو ھاڻوڪو آءِپي پتو $3 آھي، ۽ بندش سڃاڻپ $5 آهي. مھرباني ڪري ڪنھن بہ پڇا ڳاڇا يا لھوچڙ لاءِ انھن مان ڪنھن ھڪ يا ٻنھي جو حوالو ڏيندا.",
        "blockednoreason": "سبب اڻڄاڻايل",
        "whitelistedittext": "صفحا سنوارڻ لاءِ مھرباني ڪري $1.",
        "confirmedittext": "صفحا سنوارڻ کان اڳ توھان کي پنھنجي برقٽپال پتي جي تصديق ڪرڻي پوندي. مھرباني ڪري [[Special:Preferences|يوزر ترجيحن]] ذريعي پنھنجو برقٽپال پتو ڄاڻايو ۽ تصديقيو.",
        "template-protected": "(تحفظيل)",
        "template-semiprotected": "(نيم-تحفظيل)",
        "hiddencategories": "هيءُ صفحو  {{PLURAL:$1|1 لڪل زمري|$1 لڪل زمرن}}: جو رڪن آهي:",
-       "nocreatetext": "{{SITENAME}} نوان صفحا سرجڻ جي روڪَ ڪئي آهي.\nتوهان اڳي ئي موجود صفحن کي سنواري سگھو ٿا، يا [[Special:UserLogin|لاگ اِن ٿي يا نئون کاتو کولي سگھو ٿا]].",
+       "nocreatetext": "{{SITENAME}} نوان صفحا سرجڻ جي روڪَ ڪئي آھي.\nتوھان اڳ ئي موجود صفحن کي سنواري سگھو ٿا، يا [[Special:UserLogin|داخل ٿي يا نئون کاتو کولي سگھو ٿا]].",
        "nocreate-loggedin": "توهان کي نوان صفحا سرجڻ جي اجازت حاصل ڪانهي.",
        "sectioneditnotsupported-title": "سيڪشن جي سنوار ممڪن نہ آهي",
        "sectioneditnotsupported-text": "هن صفحي تي سيڪشن کي سنوارڻ ممڪن نہ آهي.",
        "permissionserrors": "اجازتنامي جي چُڪَ",
        "permissionserrorstext": "هيٺين {{PLURAL:$1|سبب|سببن}} ڪري، توهان کي اهو ڪرڻ جي اجازت حاصل ڪانهي.",
        "permissionserrorstext-withaction": "ھيٺين {{PLURAL:$1|سبب|سببن}} ڪري، توھان کي $2 جي اجازت ڪانھي.",
-       "recreate-moveddeleted-warn": "'''خبردار: توهان اهڙو صفحو نئين سِر سرجي رهيا آهيو جيڪو اڳي ڊاٺو ويو آهي.'''\n\nبهتر ٿيندو تہ توهان سوچي وٺو تہ ڇا ان صفحي کي سنوارڻ چڱو ٿيندو.\nتوهآن جي سهوليت خاطر هتي ان صفحي جو ڊاٺ لاگ ميسر ڪجي ٿو:",
+       "recreate-moveddeleted-warn": "'''خبردار: توھان اھڙو صفحو نئين سِر سرجي رھيا آھيو جيڪو اڳ ڊاٺو ويو آھي.'''\n\nبھتر ٿيندو تہ توھان سوچي وٺو تہ ڇا ان صفحي کي سنوارڻ چڱو ٿيندو.\nتوهان جي سھولت خاطر ھتي ان صفحي جو ڊاٺ لاگ ميسر ڪجي ٿو:",
        "moveddeleted-notice": "ھيءُ صفحو ڊھي چڪو آهي. \nحوالي طور ڊاٺ ۽ چور لاگ ھيٺ ڏجن ٿا.",
        "moveddeleted-notice-recent": "معاف ڪندا، هيءُ صفحو تازو ئي ڊاٺو ويو آهي (پوين 24 ڪلاڪن اندر). حوالي طور ڊاٺ ۽ چور لاگ هيٺ پيش ڪجي ٿو:",
        "log-fulllog": "پُورو لاگ ڏسو",
        "prefs-editwatchlist-label": "پنهنجي نظر ۾ فھرست ۾ درج ٿيل شين کي سنواريو:",
        "prefs-editwatchlist-edit": "پنھنجي نظر ۾ فھرست ۾ موجود عنوان ڏسو ۽ مٽايو",
        "prefs-editwatchlist-raw": "ڪچي نظر ۾ فھرست سنواريو",
-       "prefs-editwatchlist-clear": "پنهنجي نظرھيٺ فھرست ڊاهيو",
-       "prefs-watchlist-days": "نظرھيٺ فھرست ۾ ڏيکارڻ لاءِ ڏينهن:",
+       "prefs-editwatchlist-clear": "پنهنجي نظر ۾ فھرست ڊاهيو",
+       "prefs-watchlist-days": "نظر ۾ فھرست ۾ ڏيکارڻ لاءِ ڏينهن:",
        "prefs-watchlist-days-max": "وڌ ۾ وڌ $1 {{PLURAL:$1|ڏينھن}}",
        "prefs-watchlist-edits-max": "وڌ ۾ وڌ تعداد: 1000",
-       "prefs-watchlist-token": "نظرھيٺ فھرست جو ٽوڪن:",
+       "prefs-watchlist-token": "نظر ۾ فھرست جو ٽوڪن:",
        "prefs-misc": "متفرق",
        "prefs-resetpass": "ڳجھولفظ بدلايو",
-       "prefs-changeemail": "برق ٽپال پتو مِٽايو يا بدلايو",
-       "prefs-setemail": "ڪو برق ٽپال پتو ڄاڻايو",
-       "prefs-email": "برق ٽپال چارا",
+       "prefs-changeemail": "برقٽپال پتو مِٽايو يا بدلايو",
+       "prefs-setemail": "ڪو برقٽپال پتو ڄاڻايو",
+       "prefs-email": "برقٽپال چارا",
        "prefs-rendering": "حليو",
        "saveprefs": "سانڍيو",
        "prefs-editing": "سنوارڻ",
        "recentchangesdays-max": "وڌ ۾ وڌ $1 {{PLURAL:$1|ڏينهن}}",
        "recentchangescount": "عدم پيروي جي صورت ۾ ڏيکارڻ جي لاءِ ترميمون:",
        "prefs-help-recentchangescount": "ان ۾ تازيون تبديليون، صفحن جي سوانح، ۽ لاگ شامل آهن.",
-       "savedprefs": "توهان جون ترجيحات سانڍجي چڪيون آهن.",
+       "savedprefs": "توھان جون ترجيحون سانڍجي چڪيون آھن.",
        "savedrights": "{{GENDER:$1|$1}} جا يوزر گروھ سانڍجي چڪا آھن.",
        "timezonelegend": "اوقاتي زون:",
        "localtime": "مقامي وقت:",
        "timezoneregion-europe": "يُورپ",
        "timezoneregion-indian": "سنڌي ساگر",
        "timezoneregion-pacific": "ماٺو ساگر",
-       "allowemail": "ٻين يُوزرس کان ايندڙ برق ٽپال بحال ڪريو",
+       "allowemail": "ٻين يُوزرس کان ايندڙ ٽپال بحال ڪريو",
        "prefs-searchoptions": "ڳولا",
        "prefs-namespaces": "نانءُپولار",
        "default": "ڏنل",
        "prefs-files": "فائيلس",
-       "prefs-emailconfirm-label": "برق ٽپال جي خاطري:",
-       "youremail": "برق ٽپال:",
+       "prefs-emailconfirm-label": "برقٽپال خاطري:",
+       "youremail": "برقٽپال:",
        "username": "{{GENDER:$1|يُوزرنانءُ}}",
        "prefs-registration": "رجسٽريشن جو وقت:",
        "yourrealname": "اصل نالو:",
        "gender-unknown": "توهان جو ذڪر ڪندي، جيترو ٿي سگھيو، منطقگري بي جنس لفظن جو استعمال ڪندي.",
        "gender-male": "هيءُ وڪي صفحا سنواريندو آهي",
        "gender-female": "هيءَ وڪي صفحا سنواريندي آهي",
-       "email": "برق ٽپال",
+       "email": "برقٽپال",
        "prefs-help-realname": "اصل نالو اختياري آهي.\nجيڪڏهن توهان اصل نالو ڄاڻائڻ جو فيصلو ٿا ڪريو، تہ اهو توهان کي توهان جي ڪم جي مڃتا ڏيڻ لاءِ ڪم آندو ويندو.",
-       "prefs-help-email": "برق ٽپال ڄاڻائڻ اختياري آهي، پر جڏهن توهان ڳجھو لفظ وسري ويندا آهيو، تڏهن ان جو استعمال توهان کي نئون ڳجھو لفظ ڏيڻ لاءِ استعمال ڪيو ويندو آهي.",
-       "prefs-help-email-required": "برق ٽپال پتو گھربل آهي.",
+       "prefs-help-email": "برقٽپال ڄاڻائڻ اختياري آهي، پر جڏهن توهان ڳجھولفظ وسري ويندا آهيو، تڏهن ان جو استعمال توهان کي نئون ڳجھولفظ ڏيڻ لاءِ استعمال ڪيو ويندو آهي.",
+       "prefs-help-email-required": "برقٽپال پتو گھربل آهي.",
        "prefs-info": "بنيادي ڄاڻ",
        "prefs-i18n": "بين‌الاقوامڪاري",
        "prefs-signature": "صحيح",
        "right-undelete": "ڪو صفحو اڻڊاهيو",
        "right-unblockself": "ڪنهن تان بندش ختم ڪريو",
        "right-editinterface": "يُوزر باهمرُو کي سنواريو",
-       "right-viewmywatchlist": "پنهنجي نظرھيٺ فھرست ڏسو",
-       "right-editmyoptions": "پنهنجون ترجيحات سنواريو",
+       "right-viewmywatchlist": "پنهنجي نظر ۾ فھرست ڏسو",
+       "right-editmyoptions": "پنهنجون ترجيحون سنواريو",
        "right-import": "ٻين وڪيز کان صفحا درآمديو",
        "right-importupload": "ڪو فائيل چاڙهي صفحا درآمديو",
        "right-mergehistory": "صفحن جي سوانح سنواريو",
        "right-override-export-depth": "5ئين اونهائيءَ تائين ڳنڍيل صفحن سميت صفحا برآمديو",
        "right-sendemail": "ٻين يوزرس ڏانهن ايميل موڪليو",
        "right-managechangetags": "[[Special:Tags|ٽيگس]] سرجيو ۽ ڊاهيو.",
-       "grant-group-email": "برق ٽپال اماڻيو",
+       "grant-group-email": "برقٽپال اماڻيو",
        "grant-blockusers": "يُوزرس کي بندشيو ۽ اڻبندشيو",
        "grant-createaccount": "نئون کاتو کوليو",
-       "grant-editmywatchlist": "پنھنجي نظرھيٺ فھرست سنواريو",
+       "grant-editmywatchlist": "پنھنجي نظر ۾ فھرست سنواريو",
        "grant-editprotected": "تحفظيل صفحا سنواريو",
        "grant-rollback": "صفحن ۾ ڪيل تبديليون واپس ورايو",
-       "grant-sendemail": "Ù»Ù\8aÙ\86 Ù\8aÙ\88زرس Ú\8fاÙ\86Ù\87Ù\86 Ø§Ù\8aÙ\85Ù\8aل موڪليو",
+       "grant-sendemail": "Ù»Ù\8aÙ\86 Ù\8aÙ\88زرس Ú\8fاÙ\86Ù\87Ù\86 Ø¨Ø±Ù\82ٽپال موڪليو",
        "grant-uploadeditmovefile": "فائيل چاڙهيو، مَٽايو، ۽ ڊاهيو",
        "grant-uploadfile": "نئون فائيل چاڙهيو",
        "grant-basic": "بنيادي حقَ",
        "action-userrights": "سڀ يوزر حق ترميم ڪريو",
        "action-userrights-interwiki": "ٻين وڪيز جي يوزرس جا حق ترميم ڪريو",
        "action-siteadmin": "اعدادخاني کي بند ڪريو يا کوليو",
-       "action-sendemail": "برق ٽپال اماڻيو",
-       "action-editmywatchlist": "پنھنجي نظرھيٺ فھرست سنواريو",
-       "action-viewmywatchlist": "پنهنجي نظرھيٺ فھرست ڏسو",
+       "action-sendemail": "برقٽپال اماڻيو",
+       "action-editmywatchlist": "پنھنجي نظر ۾ فھرست سنواريو",
+       "action-viewmywatchlist": "پنهنجي نظر ۾ فھرست ڏسو",
        "action-viewmyprivateinfo": "پنهنجي ذاتي معلومات ڏسو",
        "action-editmyprivateinfo": "پنهنجي ذاتي معلومات سنواريو",
        "nchanges": "$1 {{PLURAL:$1|تبديلي|تبديليون}}",
        "fileuploadsummary": "خلاصو:",
        "filereuploadsummary": "فائيل تبديليون:",
        "filesource": "ذريعو:",
-       "ignorewarnings": "وارنڱس کي نظرانداز ڪريو",
+       "ignorewarnings": "چتائن کي نظرانداز ڪريو",
        "badfilename": "فائيل‌نانءُ بدلائي \"$1\" رکيو ويو آهي.",
        "empty-file": "توهان جو جمع ڪرايل فائيل خالي آهي.",
        "filename-tooshort": "فائيل نانءَُ هيڪاندو ننڍو آهي.",
        "sp-deletedcontributions-contribs": "ڀاڱيداريون",
        "linksearch-ns": "نانءُپولار",
        "linksearch-ok": "ڳوليو",
+       "listusersfrom": "تي شروع ڪندڙ يوزر ڏيکاريو:",
        "listusers-submit": "ڏيکاريو",
        "listusers-noresult": "ڪو بہ يُوزر نہ لڌو",
        "listusers-blocked": "(بندشيل)",
        "activeusers": "سرگرم يُوزرس جي فهرست",
+       "activeusers-groups": "گروھن سان تعلق رکندڙ يوزرس ڏيکاريو:",
+       "activeusers-excludegroups": "گروھن سان تعلق رکندڙ گروھ ڇڏيو:",
        "activeusers-noresult": "ڪي بہ يُوزرس نہ لڌا.",
        "activeusers-submit": "سرگرم يُوزرس ڏيکاريو",
        "listgrouprights": "يوزر گروپ جا حق",
        "listgrouprights-group": "گروهہ:",
        "listgrouprights-rights": "حق",
-       "listgrouprights-members": "(رڪÙ\86Ù\86 Ø¬Ù\8a Ù\84سٽ)",
+       "listgrouprights-members": "(رڪÙ\86Ù\86 Ø¬Ù\8a Ù\81ھرست)",
        "listgrouprights-addgroup-all": "سڀ گروپَ شامل ڪريو",
        "listgrouprights-removegroup-all": "سڀ گروپ هٽايو",
        "listgrouprights-namespaceprotection-namespace": "نانءُ پولار:",
        "emailsubject": "موضوع:",
        "emailmessage": "نياپو:",
        "emailsend": "اماڻيو",
-       "emailccme": "نياپي جو پرت مون کي برق ٽپال ڪريو.",
-       "emailsent": "برق ٽپال اماڻجي چڪي",
-       "emailsenttext": "توهان جو برق ٽپال نياپو اماڻجي چڪو آهي.",
-       "watchlist": "نظرھيٺ فھرست",
+       "emailccme": "نياپي جو پرت مون کي برقٽپال ڪريو.",
+       "emailsent": "برقٽپال اماڻجي چڪي",
+       "emailsenttext": "توهان جو برقٽپال نياپو اماڻجي چڪو آهي.",
+       "watchlist": "نظر ۾ فھرست",
        "mywatchlist": "نظر ۾ فھرست",
-       "addwatch": "نظرھيٺ فھرست ۾ شامل ڪريو",
-       "addedwatchtext": "صفحو\"[[:$1]]\" ان جي بحث وارو صفحو اوهان جي [[Special:Watchlist|نظرھيٺ فھرست]] ۾ شامل ڪيو ويو آهي.",
-       "removewatch": "نظرھيٺ فھرست مان ھٽايو",
-       "removedwatchtext": "صفحو بعنوان \"[[:$1]]\" توهان جي [[Special:Watchlist|نظرھيٺ فھرست]] مان هٽي چڪو آهي.",
-       "removedwatchtext-short": "\"صفحو بعنوان \"$1\" توهان جي نظرھيٺ فھرست مان هٽي چڪو آهي.\"",
+       "addwatch": "نظر ۾ فھرست ۾ شامل ڪريو",
+       "addedwatchtext": "صفحو\"[[:$1]]\" ان جي بحث وارو صفحو اوهان جي [[Special:Watchlist|نظر ۾ فھرست]] ۾ شامل ڪيو ويو آهي.",
+       "removewatch": "نظر ۾ فھرست مان ھٽايو",
+       "removedwatchtext": "صفحو بعنوان \"[[:$1]]\" توهان جي [[Special:Watchlist|نظر ۾ فھرست]] مان هٽي چڪو آهي.",
+       "removedwatchtext-short": "\"صفحو بعنوان \"$1\" توهان جي نظر ۾ فھرست مان هٽي چڪو آهي.\"",
        "watch": "نظر ۾ رکو",
-       "watchthispage": "هيءُ صفحو نظرھيٺ رکو",
-       "unwatch": "نظرھيٺ نہ رکو",
-       "unwatchthispage": "نظرھيٺ رکڻ ڇڏيو",
+       "watchthispage": "هيءُ صفحو نظر ۾ رکو",
+       "unwatch": "نظر ۾ نہ رکو",
+       "unwatchthispage": "نظر ۾ رکڻ ڇڏيو",
        "notanarticle": "غير موادي صفحو",
        "watchlist-details": "{{PLURAL:$1|$1 صفحو|$1 صفحا}} توهان جي ٽيٽ فهرست، ڳالھ ٻولھ جا صفحا الڳ شمار نٿا ٿين.",
        "wlshowlast": "گذريل $1 ڪلاڪ $2 ڏينهن ڏيکاريو",
        "wlshowhideliu": "کاتيدار يُوزرس",
        "wlshowhideanons": "گمنام يُوزرس",
        "wlshowhidemine": "منهنجون ترميمون",
-       "watchlist-options": "نظرھيٺ فھرست جا چارا",
-       "watching": "نظرھيٺ رکندي...",
-       "unwatching": "نظرھيٺان ڪڍندي...",
+       "watchlist-options": "نظر ۾ فھرست جا چارا",
+       "watching": "نظر ۾ رکندي...",
+       "unwatching": "نظر مان ڪڍندي...",
        "enotif_reset": "سڀ گھميل صفحن تي نشان لڳايو",
        "enotif_impersonal_salutation": "{{SITENAME}} يُوزر",
        "enotif_lastdiff": "هي تبديلي ڏسڻ لاءِ $1 ڏسو",
        "blocklink": "بندشيو",
        "unblocklink": "اڻبندشيو",
        "contribslink": "ڀاڱيداريون",
-       "emaillink": "برق ٽپال اماڻيو",
+       "emaillink": "برقٽپال اماڻيو",
        "blocklogpage": "بندش لاگ",
        "blocklogentry": "\"[[$1]]\" کي بندشيو ويو $2 $3 جي عرصي لاء",
        "unblocklogentry": "$1 تان بندش هٽائي وئي",
        "block-log-flags-anononly": "فقط نامعلوم يوزرس",
-       "block-log-flags-noemail": "برق ٽپال غير فعال",
+       "block-log-flags-noemail": "برقٽپال غير فعال",
        "block-log-flags-hiddenname": "لڪل يُوزرنانءُ",
        "ipb_already_blocked": "\"$1\" اڳ ۾ ئي بندشيل آهي.",
        "ipbnounblockself": "توهان پنهنجو پاڻ تان بندش هٽائي نہ ٿا سگھو.",
        "tooltip-ca-delete": "هيءُ صفحو ڊاهيو",
        "tooltip-ca-move": "ھيءُ صفحو چوريو",
        "tooltip-ca-watch": "هيءُ صفحو پنهنجي نظر ۾ فھرست ۾ شامل ڪريو",
-       "tooltip-ca-unwatch": "هيءُ صفحو پنهنجي نظرھيٺ فھرست تان هٽايو",
+       "tooltip-ca-unwatch": "هيءُ صفحو پنهنجي نظر ۾ فھرست تان هٽايو",
        "tooltip-search": "{{SITENAME}} ۾ ڳوليو",
        "tooltip-search-go": "تز ان ئي نالي سان ڪو صفحو موجود آھي تہ کوليو",
        "tooltip-search-fulltext": "ھن متن لاءِ صفحا ڳوليو",
        "tooltip-t-recentchangeslinked": "ويجھڙائيءَ ۾ صفحن ۾ ٿيل تبديليون هن صفحي سان ڳنڍيل آهن",
        "tooltip-feed-atom": "هن صفحي لاءِ ايٽم فيڊ",
        "tooltip-t-contributions": "{{GENDER:$1|ھن يوزر}} جي ڀاڱيدارين جي فھرست",
-       "tooltip-t-emailuser": "{{GENDER:$1|Ú¾Ù\86 Ù\8aÙ\88زر}} Ú\8fاÙ\86Ú¾Ù\86 Ø§Ù\8aÙ\85Ù\8aل موڪليو",
+       "tooltip-t-emailuser": "{{GENDER:$1|Ú¾Ù\86 Ù\8aÙ\88زر}} Ú\8fاÙ\86Ú¾Ù\86 Ø¨Ø±Ù\82ٽپال موڪليو",
        "tooltip-t-upload": "فائيل چاڙهيو",
        "tooltip-t-specialpages": "سڀني خاص صفحن جي فھرست",
        "tooltip-t-print": "هن صفحي جو ڇاپائتو پرت",
        "tooltip-preview": "پنھنجي تبديلين تي نگاھ وجھو. براءِ مھرباني اھو سانڍڻ کان اڳ ڪندا.",
        "tooltip-diff": "لکت ۾ ڪيل پنھنجون تبديليون ڏسو",
        "tooltip-compareselectedversions": "هن صفحي جن ٻن چونڊيل پرتن درميان تفاوت ڏسو.",
-       "tooltip-watch": "هيءُ صفحو پنهنجي نظرھيٺ فھرست ۾ شامل ڪريو",
+       "tooltip-watch": "هيءُ صفحو پنهنجي نظر ۾ فھرست ۾ شامل ڪريو",
        "tooltip-rollback": "\"واپس ورايو\" ھن صفحي ۾ پوئين ڀاڱيدار جي ڪيل ترميم(ن) کي ھڪ ٽڙڪ سان اڻڪري ٿو",
        "tooltip-summary": "ننڍو خلاصو ڏيو",
        "anonymous": "گمنام {{PLURAL:$1|يوزر|يوزرس}} جو {{SITENAME}}",
        "exif-saturation-0": "نارمل",
        "exif-saturation-1": "ننڍ رچاءُ",
        "exif-saturation-2": "وَڏ رچاءُ",
-       "exif-sharpness-0": "نارمل",
+       "exif-sharpness-0": "رواجي",
        "exif-subjectdistancerange-0": "نامعلوم",
        "exif-subjectdistancerange-3": "ڏورانهين نگاهہ",
        "exif-gpslatitude-s": "ڏاکڻي ويڪرائي ڦاڪَ",
        "exif-iimcategory-wea": "موسم",
        "namespacesall": "سڀ",
        "monthsall": "سڀ",
-       "confirmemail": "برق ٽپال پتي جي پَڪَ ڪندا",
+       "confirmemail": "برقٽپال پتي جي پَڪَ ڪندا",
        "confirmemail_send": "خاطري ڪوڊ اماڻيو",
-       "confirmemail_sent": "خاطري برق ٽپال اماڻي وئي.",
-       "confirmemail_success": "توهان جي برق ٽپال پتي جي تصديق ڪئي وئي آهي.\nهاڻ توهان [[Special:UserLogin|لاگ اِن]] ٿي ۽ وڪي جو مزو وٺي سگھو ٿا.",
-       "confirmemail_loggedin": "توهان جي برق ٽپال پتي جي تصديق هاڻي ٿي چڪي آهي.",
-       "confirmemail_subject": "{{SITENAME}} برق ٽپال پتي جي تصديق",
+       "confirmemail_sent": "خاطري برقٽپال اماڻي وئي.",
+       "confirmemail_success": "توهان جي برقٽپال پتي جي تصديق ڪئي وئي آهي.\nهاڻ توهان [[Special:UserLogin|داخل ٿي]] ۽ وڪي جو مزو وٺي سگھو ٿا.",
+       "confirmemail_loggedin": "توهان جي برقٽپال پتي جي تصديق هاڻي ٿي چڪي آهي.",
+       "confirmemail_subject": "{{SITENAME}} برقٽپال پتي جي تصديق",
        "recreate": "ورسرجيو",
        "confirm-watch-button": "ٺيڪ",
-       "confirm-watch-top": "هيءُ صفحو پنهنجي نظرھيٺ فھرست ۾ شامل ڪندا؟",
+       "confirm-watch-top": "هيءُ صفحو پنهنجي نظر ۾ فھرست ۾ شامل ڪندا؟",
        "confirm-unwatch-button": "ٺيڪ",
-       "confirm-unwatch-top": "Ù\87Ù\8aØ¡Ù\8f ØµÙ\81Ø­Ù\88 Ù¾Ù\86Ù\87Ù\86جÙ\8a Ù½Ù\8aÙ½ فهرست مان هٽائيندا؟",
+       "confirm-unwatch-top": "Ù\87Ù\8aØ¡Ù\8f ØµÙ\81Ø­Ù\88 Ù¾Ù\86Ù\87Ù\86جÙ\8a Ù\86ظر Û¾ فهرست مان هٽائيندا؟",
        "quotation-marks": "\"$1\"",
        "imgmultipageprev": "← اڳوڻو صفحو",
        "imgmultipagenext": "ايندڙ صفحو →",
        "table_pager_limit_label": "وَٿُون في صفحو:",
        "table_pager_limit_submit": "ھلو",
        "table_pager_empty": "ڪو بہ نتيجو نہ مليو",
-       "watchlistedit-normal-title": "نظرھيٺ فھرست کي سنواريو",
+       "watchlistedit-normal-title": "نظر ۾ فھرست کي سنواريو",
        "watchlistedit-raw-titles": "عنوانَ:",
        "watchlistedit-clear-titles": "عنوانَ:",
        "watchlisttools-view": "لاڳاپيل تبديليون ڏسو",
-       "watchlisttools-edit": "Ù½Ù\8aÙ½ فهرست ڏسو ۽ سنواريو",
-       "watchlisttools-raw": "ÚªÚ\86Ù\8a Ù½Ù\8aÙ½ Ù\81Ù\87رست سنواريو",
+       "watchlisttools-edit": "Ù\86ظر Û¾ فهرست ڏسو ۽ سنواريو",
+       "watchlisttools-raw": "ÚªÚ\86Ù\8a Ù\86ظر Û¾ Ù\81Ú¾رست سنواريو",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|ڳالھ]])",
        "version": "ڀيرو",
        "version-extensions": "تنصيب شده توسيعات",
        "fileduplicatesearch-submit": "ڳوليو",
        "specialpages": "خاص صفحا",
        "specialpages-note-top": "ڪُنجي",
-       "specialpages-group-login": "لاگ اِن ٿيو / کاتو کوليو",
+       "specialpages-group-login": "داخل ٿيو / کاتو کوليو",
        "specialpages-group-users": "يوزرس ۽ حق",
        "blankpage": "خالي صفحو",
        "intentionallyblankpage": "هيءُ صفحو ڄاڻي خالي ڇڏيو ويو آهي.",
index 3b9d58c..8bb9827 100644 (file)
        "blockedtitle": "Uporabnik je blokiran",
        "blockedtext": "'''Urejanje z vašim uporabniškim imenom oziroma IP-naslovom je onemogočeno.'''\n\nBlokiral vas je $1.\nPodani razlog je ''$2''.\n\n* začetek blokade: $8\n* potek blokade: $6\n* blokirani uporabnik: $7\n\nO blokiranju se lahko pogovorite z uporabnikom/-co $1 ali katerim drugim [[{{MediaWiki:Grouppage-sysop}}|administratorjem]].\nVedite, da lahko ukaz »Pošlji uporabniku e-pismo« uporabite le, če ste v [[Special:Preferences|nastavitvah]] vpisali in potrdili svoj elektronski naslov in ta ni blokiran.\nVaš IP-naslov je $3, številka blokade pa #$5.\nProsimo, vključite ju v vse morebitne poizvedbe.",
        "autoblockedtext": "Vaš IP-naslov je bil samodejno blokiran, saj je bil uporabljen s strani drugega uporabnika, ki ga je blokiral $1.\nRazlog za to je bil naslednji:\n\n:''$2''\n\n* Začetek blokade: $8\n* Konec blokade: $6\n* Blokirani uporabnik: $7\n\nKontaktirate lahko $1 ali katerega od drugih [[{{MediaWiki:Grouppage-sysop}}|administratorjev]], da razpravljate o blokadi.\n\nVedite, da lahko funkcijo »{{:MediaWiki:Emailuser/sl}}« uporabljate le, če ste v svoje [[Special:Preferences|uporabniške nastavitve]] vnesli veljaven e-poštni naslov, in vam njena uporaba ni bila preprečena.\n\nVaš trenutni IP-naslov je $3, ID blokiranja pa #$5. Prosimo, vključite ta ID v vsako zastavljeno vprašanje.",
+       "systemblockedtext": "Vaše uporabniško ime ali IP-naslov je MediaWiki samodejn blokiral.\nPodani razlog je:\n\n:<em>$2</em>\n\n* Začetek blokade: $8\n* Potek blokade: $6\n* Blokirani uporabnik: $7\n\nVaš trenutni IP-naslov je $3.\nProsimo, da v svoje poizvedbe vključite vse zgornje podatke.",
        "blockednoreason": "razlog ni podan",
        "whitelistedittext": "Za urejanje strani se morate $1.",
        "confirmedittext": "Pred urejanjem strani morate potrditi svoj e-poštni naslov.\nProsimo, da ga z uporabo [[Special:Preferences|uporabniških nastavitev]] vpišete in potrdite.",
        "pageinfo-length": "Dolžina strani (v bajtih)",
        "pageinfo-article-id": "ID strani",
        "pageinfo-language": "Jezik vsebine strani",
+       "pageinfo-language-change": "spremeni",
        "pageinfo-content-model": "Model vsebine strani",
        "pageinfo-content-model-change": "spremeni",
        "pageinfo-robot-policy": "Robotsko indeksiranje",
        "restrictionsfield-badip": "Neveljaven IP-naslov ali obseg: $1",
        "restrictionsfield-label": "Dovoljeni IP-obsegi:",
        "restrictionsfield-help": "En IP-naslov ali CIDR-območje na vrstico. Da omogočite vse, uporabite<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "redakcija $1",
        "pageid": "ID strani $1"
 }
index d4f9cbb..cd7588f 100644 (file)
        "blockedtitle": "Användaren är blockerad",
        "blockedtext": "'''Din IP-adress eller ditt användarnamn är blockerat.'''\n\nBlockeringen utfördes av $1 med motiveringen: ''$2''.\n\n* Blockeringen startade: $8\n* Blockeringen gäller till: $6.\n* Blockeringen var avsedd för: $7.\n\nDu kan kontakta $1 eller någon annan av [[{{MediaWiki:Grouppage-sysop}}|administratörerna]] för att diskutera blockeringen.\nOm du är inloggad och har uppgivit en e-postadress i dina [[Special:Preferences|inställningar]] så kan du använda funktionen 'Skicka e-post till den här användaren', såvida du inte blivit blockerad från funktionen.\n\nDin IP-adress är $3 och blockerings-ID är #$5.\nVänligen ange informationen ovan i alla förfrågningar som du gör i ärendet.",
        "autoblockedtext": "Din IP-adress har blockerats automatiskt eftersom den har använts av en annan användare som blockerats av $1.\nMotiveringen av blockeringen var:\n\n:''$2''\n\n* Blockeringen startade: $8\n* Blockeringen gäller till: $6\n* Blockeringen är avsedd för: $7\n\nDu kan kontakta $1 eller någon annan [[{{MediaWiki:Grouppage-sysop}}|administratör]] för att diskutera blockeringen.\n\nObservera att du inte kan använda dig av funktionen \"skicka e-post till användare\" om du inte har registrerat en giltig e-postadress i [[Special:Preferences|dina inställningar]] eller om du har blivit blockerad från att skicka e-post.\n\nDin nuvarande IP-adress är $3, och blockerings-ID är #$5.\nVänligen ange informationen ovan i alla förfrågningar som du gör i ärendet.",
+       "systemblockedtext": "Ditt användarnamn eller IP-adress h    ar blockerats automatiskt av MediaWiki.\n\nMotiveringen av blockeringen var:\n\n:<em>$2</em>\n\n* Blockeringen startade: $8\n* Blockeringen gäller till: $6\n* Blockeringen är avsedd för: $7\n\nDin nuvarande IP-adress är $3.\nVänligen ange informationen ovan i alla förfrågningar som du gör i ärendet.",
        "blockednoreason": "ingen motivering angavs",
        "whitelistedittext": "Vänligen $1 för att redigera sidor.",
        "confirmedittext": "Du måste bekräfta din e-postadress innan du kan redigera sidor. Var vänlig ställ in och validera din e-postadress genom dina [[Special:Preferences|användarinställningar]].",
        "emailccsubject": "Kopia av ditt meddelande till $1: $2",
        "emailsent": "E-post har nu skickats",
        "emailsenttext": "Ditt e-postmeddelande har skickats",
-       "emailuserfooter": "Detta e-postmeddelande {{GENDER:$1|skickades}} av $1 till {{GENDER:$2|$2}} med funktionen \"{{int:emailuser}}\" på {{SITENAME}}. {{GENDER:$2|Ditt}} e-postmeddelande kommer att skickas direkt till {{GENDER:$1|den ursprungliga avsändaren}}, vilket kommer avslöja {{GENDER:$2|din}} e-postadress för {{GENDER:$1|dem}}.",
+       "emailuserfooter": "Detta e-postmeddelande {{GENDER:$1|skickades}} av $1 till {{GENDER:$2|$2}} med funktionen \"{{int:emailuser}}\" på {{SITENAME}}. {{GENDER:$2|Ditt}} e-postmeddelande kommer att skickas direkt till {{GENDER:$1|den ursprungliga avsändaren}}, vilket kommer avslöja {{GENDER:$2|din}} e-postadress för {{GENDER:$1|honom|henne|hen}}.",
        "usermessage-summary": "Lämnar systemmeddelande.",
        "usermessage-editor": "Systemmeddelare",
        "watchlist": "Bevakningslista",
        "pageinfo-length": "Sidlängd (i byte)",
        "pageinfo-article-id": "Sid-ID",
        "pageinfo-language": "Språk för sidinnehåll",
+       "pageinfo-language-change": "ändra",
        "pageinfo-content-model": "Sidinnehållsmodell",
        "pageinfo-content-model-change": "ändra",
        "pageinfo-robot-policy": "Indexering av robotar",
        "restrictionsfield-badip": "Ogiltig IP-adress eller intervall: $1",
        "restrictionsfield-label": "Tillåtna IP-intervall:",
        "restrictionsfield-help": "En IP-adress eller CIDR-intervall per rad. För att aktivera allting, använd<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "sidversion $1",
        "pageid": "sid-ID $1"
 }
index bf81066..ad5535e 100644 (file)
@@ -39,7 +39,7 @@
        "tog-usenewrc": "จัดกลุ่มการเปลี่ยนแปลงแบ่งตามหน้าในรายการปรับปรุงล่าสุดและรายการเฝ้าดู",
        "tog-numberheadings": "กำหนดเลขหัวเรื่องอัตโนมัติ",
        "tog-showtoolbar": "แสดงแถบเครื่องมือแก้ไข",
-       "tog-editondblclick": "à¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¹\80มืà¹\88อà¸\94ัà¸\9aà¹\80à¸\9aิลà¸\84ลิà¸\81",
+       "tog-editondblclick": "à¹\81à¸\81à¹\89à¹\84à¸\82หà¸\99à¹\89าà¹\80มืà¹\88อà¸\84ลิà¸\81สอà¸\87à¸\84รัà¹\89à¸\87",
        "tog-editsectiononrightclick": "เปิดใช้งานการแก้ไขส่วนโดยคลิกขวาที่ชื่อเรื่องของส่วนนั้น",
        "tog-watchcreations": "เพิ่มหน้าที่ฉันสร้างและไฟล์ที่ฉันอัปโหลดเข้ารายการเฝ้าดู",
        "tog-watchdefault": "เพิ่มหน้าและไฟล์ที่ฉันแก้ไขเข้ารายการเฝ้าดู",
        "delete": "ลบ",
        "deletethispage": "ลบหน้านี้",
        "undeletethispage": "กู้คืนหน้านี้",
-       "undelete_short": "กู้คืน $1 การแก้ไข",
+       "undelete_short": "กู้คืนการแก้ไข $1 ครั้ง",
        "viewdeleted_short": "ดู $1 การแก้ไขที่ถูกลบ",
        "protect": "ล็อก",
        "protect_change": "เปลี่ยน",
        "mycustomjsprotected": "คุณไม่มีสิทธิแก้ไขหน้าจาวาสคริปต์นี้",
        "myprivateinfoprotected": "คุณไม่มีสิทธิแก้ไขข้อมูลส่วนตัวของคุณ",
        "mypreferencesprotected": "คุณไม่มีสิทธิแก้ไขการตั้งค่าของคุณ",
-       "ns-specialprotected": "ไม่สามารถแก้ไขหน้าพิเศษ",
+       "ns-specialprotected": "ไม่สามารถแก้ไขหน้าพิเศษได้",
        "titleprotected": "ชื่อเรื่องนี้ถูก [[User:$1|$1]] ป้องกันมิให้สร้าง\nเหตุผลที่ให้ไว้คือ <em>$2</em>",
        "filereadonlyerror": "ไม่สามารถแก้ไขไฟล์ \"$1\" เพราะที่เก็บไฟล์ \"$2\" อยู่ในภาวะอ่านอย่างเดียว\n\nผู้ดูแลระบบที่ล็อกให้คำอธิบายว่า: \"$3\"",
        "invalidtitle-knownnamespace": "ชื่อเรื่องที่มีเนมสเปซ \"$2\" กับข้อความ \"$3\" ไม่ถูกต้อง",
        "previewnote": "<strong>พึงระลึกว่านี่เป็นเพียงการแสดงตัวอย่าง</strong>\nยังไม่ได้บันทึกการเปลี่ยนแปลงของคุณ!",
        "continue-editing": "ไปพื้นที่แก้ไข",
        "previewconflict": "ตัวอย่างนี้สะท้อนข้อความในพื้นที่แก้ไขข้อความส่วนบนซึ่งจะปรากฏหากคุณเลือกบันทึก",
-       "session_fail_preview": "<strong>ขออภัย! ไม่สามารถดำเนินการแก้ไขของคุณได้ เนื่องจากข้อมูลช่วงเวลาสื่อสารสูญหาย</strong>\nโปรดลองอีกครั้ง \nหากยังเสียอยู่ ลอง[[Special:UserLogout|ล็อกเอาต์]]และล็อกอินกลับมา",
-       "session_fail_preview_html": "<strong>ขออภัย! ไม่สามารถดำเนินการแก้ไขของคุณต่อได้ เนื่องจากข้อมูลช่วงเวลาสื่อสารสูญหาย</strong>\n\n<em>เนื่องจาก {{SITENAME}} เปิดใช้งานเอชทีเอ็มแอลล้วน การแสดงตัวอย่างจะถูกซ่อนไว้เพื่อป้องกันการโจมตีด้วยจาวาสคริปต์</em>\n\n<strong>หากนี่เป็นความพยายามแก้ไขโดยชอบ โปรดลองอีกครั้งหนึ่ง</strong> \nหากยังเสียอยู่ ลอง[[Special:UserLogout|ล็อกเอาต์]]และล็อกอินกลับมา",
+       "session_fail_preview": "ขออภัย! เราไม่สามารถดำเนินการแก้ไขของคุณได้ เนื่องจากข้อมูลช่วงเวลาสื่อสารสูญหาย\n\nคุณอาจล็อกเอาต์ไปแล้ว <strong>โปรดตรวจดูให้แน่ใจว่าคุณล็อกอินอยู่ แล้วลองอีกครั้ง</strong> \nหากยังเสียอยู่ ลอง[[Special:UserLogout|ล็อกเอาต์]]และล็อกอินกลับมา แล้วตรวจดูว่าเบราว์เซอร์ที่คุณใช้อนุญาตคุกกี้จากไซต์นี้",
+       "session_fail_preview_html": "ขออภัย! ไม่สามารถดำเนินการแก้ไขของคุณต่อได้ เนื่องจากข้อมูลช่วงเวลาสื่อสารสูญหาย\n\n<em>เนื่องจาก {{SITENAME}} เปิดใช้งานเอชทีเอ็มแอลล้วน การแสดงตัวอย่างจะถูกซ่อนไว้เพื่อป้องกันการโจมตีด้วยจาวาสคริปต์</em>\n\n<strong>หากนี่เป็นความพยายามแก้ไขโดยชอบ โปรดลองอีกครั้งหนึ่ง</strong> \nหากยังเสียอยู่ ลอง[[Special:UserLogout|ล็อกเอาต์]]และล็อกอินกลับมา และตรวจดูให้แน่ใจว่าเบราว์เซอร์ที่คุณใช้อนุญาตคุกกี้จากไซต์นี้",
        "token_suffix_mismatch": "<strong>การแก้ไขของคุณถูกปฏิเสธ เนื่องจากเครื่องลูกข่ายของคุณทำให้อักขระเครื่องหมายวรรคตอนในโทเค็นการแก้ไขเสีย</strong>\nการแก้ไขนี้ถูกปฏิเสธเพื่อป้องกันการวิบัติของข้อความหน้า\nบางครั้งเกิดปัญหานี้ขึ้นเมื่อคุณใช้บริการเว็บพร็อกซีนิรนามที่มีจุดบกพร่อง",
        "edit_form_incomplete": "<strong>แบบแก้ไขบางส่วนไปไม่ถึงเซิร์ฟเวอร์ ตรวจสอบอีกครั้งว่าการแก้ไขของคุณยังอยู่และลองอีกครั้ง</strong>",
        "editing": "กำลังแก้ไข $1",
        "prefswarning-warning": "คุณเปลี่ยนแปลงการตั้งค่าของคุณที่ยังไม่ได้บันทึก\nหากคุณออกจากหน้านี้โดยไม่คลิก \"$1\" จะไม่ปรับการตั้งค่าของคุณ",
        "prefs-tabs-navigation-hint": "แนะนำ: คุณสามารถใช้แป้นลูกศรซ้ายและขวาเพื่อนำทางระหว่างแถบในรายการแถบได้",
        "userrights": "การบริหารสิทธิผู้ใช้",
-       "userrights-lookup-user": "à¸\9aริหารà¸\81ลุà¹\88มผู้ใช้",
+       "userrights-lookup-user": "à¹\80ลือà¸\81ผู้ใช้",
        "userrights-user-editname": "ใส่ชื่อผู้ใช้:",
-       "editusergroup": "à¹\81à¸\81à¹\89à¹\84à¸\82à¸\81ลุà¹\88ม{{GENDER:$1|à¸\9cูà¹\89à¹\83à¸\8aà¹\89}}",
+       "editusergroup": "à¹\82หลà¸\94à¸\81ลุà¹\88มà¸\9cูà¹\89à¹\83à¸\8aà¹\89",
        "editinguser": "กำลังเปลี่ยนสิทธิผู้ใช้ของผู้ใช้ <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "แก้ไขกลุ่มผู้ใช้",
        "saveusergroups": "บันทึกกลุ่ม{{GENDER:$1|ผู้ใช้}}",
        "rightslogtext": "นี่คือปูมการเปลี่ยนแปลงสิทธิผู้ใช้",
        "action-read": "อ่านหน้านี้",
        "action-edit": "แก้ไขหน้านี้",
-       "action-createpage": "สร้างหน้า",
-       "action-createtalk": "สร้างหน้าอภิปราย",
+       "action-createpage": "สร้างหน้านี้",
+       "action-createtalk": "สร้างหน้าอภิปรายนี้",
        "action-createaccount": "สร้างบัญชีผู้ใช้นี้",
        "action-history": "ดูประวัติหน้านี้",
        "action-minoredit": "ทำเครื่องหมายการแก้ไขนี้เป็นการแก้ไขเล็กน้อย",
        "action-upload_by_url": "อัปโหลดไฟล์นี้จากยูอาร์แอล",
        "action-writeapi": "ใช้การเขียนเอพีไอ",
        "action-delete": "ลบหน้านี้",
-       "action-deleterevision": "ลบรุ่นปรับปรุงนี้",
-       "action-deletedhistory": "à¸\94ูà¸\9bระวัà¸\95ิà¸\97ีà¹\88à¸\96ูà¸\81ลà¸\9aà¸\82อà¸\87หà¸\99à¹\89าà¸\99ีà¹\89",
+       "action-deleterevision": "ลบรุ่นปรับปรุง",
+       "action-deletedhistory": "à¸\94ูà¸\9bระวัà¸\95ิà¸\97ีà¹\88à¸\96ูà¸\81ลà¸\9aà¸\82อà¸\87หà¸\99à¹\89าà¹\83à¸\94หà¸\99à¹\89าหà¸\99ึà¹\88à¸\87",
        "action-browsearchive": "ค้นหาหน้าที่ถูกลบ",
-       "action-undelete": "กู้คืนหน้านี้",
-       "action-suppressrevision": "à¸\97à¸\9aà¸\97วà¸\99à¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99รุà¹\88à¸\99à¸\9bรัà¸\9aà¸\9bรุà¸\87à¸\97ีà¹\88à¸\8bà¹\88อà¸\99อยูà¹\88à¸\99ีà¹\89",
+       "action-undelete": "กู้คืนหน้า",
+       "action-suppressrevision": "à¸\95รวà¸\88à¸\97าà¸\99à¹\81ละà¸\81ูà¹\89à¸\84ืà¸\99รุà¹\88à¸\99à¸\9bรัà¸\9aà¸\9bรุà¸\87à¸\97ีà¹\88à¸\8bà¹\88อà¸\99อยูà¹\88",
        "action-suppressionlog": "ดูปูมส่วนตัวนี้",
        "action-block": "บล็อกผู้ใช้นี้มิให้แก้ไข",
        "action-protect": "เปลี่ยนระดับการล็อกสำหรับหน้านี้",
        "recentchangeslinked-page": "ชื่อหน้า:",
        "recentchangeslinked-to": "แสดงการเปลี่ยนแปลงไปหน้าซึ่งโยงไปหน้าที่ระบุแทน",
        "recentchanges-page-added-to-category": "[[:$1]] ถูกเพิ่มเข้าหมวดหมู่",
-       "recentchanges-page-added-to-category-bundled": "[[:$1]] à¹\81ละ $2 à¸«à¸\99à¹\89าà¸\96ูà¸\81à¹\80à¸\9eิà¹\88มà¹\80à¸\82à¹\89าหมวà¸\94หมูà¹\88",
+       "recentchanges-page-added-to-category-bundled": "[[:$1]] à¸\96ูà¸\81à¹\80à¸\9eิà¹\88มà¹\80à¸\82à¹\89าหมวà¸\94หมูà¹\88à¹\81ลà¹\89ว [[Special:WhatLinksHere/$1|หà¸\99à¹\89าà¸\99ีà¹\89รวมà¸\96ึà¸\87ภายà¹\83à¸\99หà¸\99à¹\89าอืà¹\88à¸\99à¹\86 à¸\94à¹\89วย]]",
        "recentchanges-page-removed-from-category": "[[:$1]] ถูกลบจากหมวดหมู่",
-       "recentchanges-page-removed-from-category-bundled": "[[:$1]] à¹\81ละ $2 à¸«à¸\99à¹\89าà¸\96ูà¸\81ลà¸\9aà¸\88าà¸\81หมวà¸\94หมูà¹\88",
+       "recentchanges-page-removed-from-category-bundled": "[[:$1]] à¸\96ูà¸\81ลà¸\9aà¸\88าà¸\81หมวà¸\94หมูà¹\88à¹\81ลà¹\89ว [[Special:WhatLinksHere/$1|หà¸\99à¹\89าà¸\99ีà¹\89รวมà¸\96ึà¸\87ภายà¹\83à¸\99หà¸\99à¹\89าอืà¹\88à¸\99à¹\86 à¸\94à¹\89วย]]",
        "autochange-username": "การเปลี่ยนแปลงอัตโนมัติมีเดียวิกิ",
        "upload": "อัปโหลดไฟล์",
        "uploadbtn": "อัปโหลดไฟล์",
        "filedelete-maintenance": "ปิดใช้งานการลบและกู้คืนไฟล์ชั่วคราวระหว่างการบำรุงรักษา",
        "filedelete-maintenance-title": "ไม่สามารถลบไฟล์",
        "mimesearch": "ค้นหาไมม์",
-       "mimesearch-summary": "หน้านี้แสดงไฟล์ตามการแบ่งของชนิดไมม์ของแต่ละไฟล์ \nใส่ค่า: contenttype/subtype เช่น <code>image/jpeg</code>",
+       "mimesearch-summary": "หà¸\99à¹\89าà¸\99ีà¹\89à¹\81สà¸\94à¸\87à¹\84à¸\9fลà¹\8cà¸\95ามà¸\81ารà¹\81à¸\9aà¹\88à¸\87à¸\82อà¸\87à¸\8aà¸\99ิà¸\94à¹\84มมà¹\8cà¸\82อà¸\87à¹\81à¸\95à¹\88ละà¹\84à¸\9fลà¹\8c \nà¹\83สà¹\88à¸\84à¹\88า: contenttype/subtype à¸«à¸£à¸·à¸­ contenttype/* à¹\80à¸\8aà¹\88à¸\99 <code>image/jpeg</code>",
        "mimetype": "ชนิดไมม์:",
        "download": "ดาวน์โหลด",
        "unwatchedpages": "หน้าที่ไม่มีผู้เฝ้าดู",
index 8b36833..12fb84b 100644 (file)
@@ -90,7 +90,8 @@
                        "Ece Alpdeniz",
                        "Superyetkin",
                        "Alikaan",
-                       "By erdo can"
+                       "By erdo can",
+                       "1917 Ekim Devrimi"
                ]
        },
        "tog-underline": "Bağlantıların altını çiz:",
        "changecontentmodel-submit": "Değiştir",
        "changecontentmodel-success-title": "İçerik modeli değiştirildi",
        "changecontentmodel-success-text": "İçerik türü [[:$1]] olarak değiştirildi.",
+       "log-name-contentmodel": "İçerik modeli değiştirme günlüğü",
        "logentry-contentmodel-change-revertlink": "Eski haline döndür",
        "logentry-contentmodel-change-revert": "Eski haline döndür",
        "protectlogpage": "Koruma kayıtları",
        "htmlform-user-not-exists": "<strong>$1</strong> mevcut değil.",
        "htmlform-user-not-valid": "<strong>$1</strong> geçerli bir kullanıcı ismi değildir.",
        "logentry-delete-delete": "$1 $3 sayfasını {{GENDER:$2|sildi}}",
+       "logentry-delete-delete_redir": "$1, $3 yönlendirmesini üzerine yazılması için {{GENDER:$2|sildi}}",
        "logentry-delete-restore": "$1 $3 sayfasını {{GENDER:$2|geri getirdi}}",
        "logentry-delete-event": "$1, $3 sayfasında {{PLURAL:$5|bir günlük girdisinin |$5 günlük girdisinin}} görünürlüğünü {{GENDER:$2|değiştirdi}}: $4",
        "logentry-delete-revision": "$1, $3 sayfasında {{PLURAL:$5|bir sürümün|$5 sürümün}} görünürlüğünü {{GENDER:$2|değiştirdi}}: $4",
index 9eb40e0..6bac24f 100644 (file)
        "missingcommenttext": "Аска тасвирлама язуыгыз сорала.",
        "missingcommentheader": "<strong>Искәртү:</strong> Сез шәрехнең темасын күрсәтмәгәнсез.\n«{{int:savearticle}}» төймәсенә кабат бассагыз, үзгәртүләр темасыз язылачак.",
        "summary-preview": "Тасвирламаны алдан карау:",
-       "subject-preview": "Башисемне болай булачак:",
+       "subject-preview": "Башисем шушындый булачак:",
        "blockedtitle": "Кулланучы тыелды",
        "blockedtext": "'''Сезнең хисап язмагыз яки IP адресыгыз тыелган.'''\n\nТыючы идарәче: $1.\nКүрсәтелгән сәбәп: ''$2''.\n\n* Тыю башланган вакыт: $8\n* Тыю ахыры: $6\n* Тыелулар саны: $7\n\nСез $1 яки башка [[{{MediaWiki:Grouppage-sysop}}|идарәчегә]] тыю буенча сорауларыгызны җибәрә аласыз.\nИсегездә тотыгыз: әгәр сез теркәлмәгән һәм электрон почта адресыгызны дәлилләмәгән булсагыз ([[Special:Preferences|дәлилләү өчен шәхси көйләүләр монда]]), идарәчегә хат җибәрә алмыйсыз. Шулай ук тыю вакытында сезнең хат җибәрү мөмкинлегегезне чикләгән булырга да мөмкиннәр.\nСезнең IP адресы — $3, тыю идентификаторы — #$5.\nХатларда бу мәгълүматны күрсәтергә онытмагыз.",
        "autoblockedtext": "Сезнең IP адресыгыз, аның тыелган кулланучы тарафыннан кулланылуы сәбәпле, автомат рәвештә тыелды.\nУл кулланучыны тыючы идарәче: $1. Күрсәтелгән сәбәп:\n\n:''$2''\n\n* Тыю башланган вакыт: $8\n* Тыю ахыры: $6\n* Тыелулар саны: $7\n\nСез $1 яки башка [[{{MediaWiki:Grouppage-sysop}}|идарәчегә]] тыю буенча сорауларыгызны җибәрә аласыз.\nИсегездә тотыгыз: әгәр сез теркәлмәгән һәм электрон почта адресыгызны дәлилләмәгән булсагыз ([[Special:Preferences|дәлилләү өчен шәхси көйләүләр монда]]), идарәчегә хат җибәрә алмыйсыз. Шулай ук тыю вакытында сезнең хат җибәрү мөмкинлегегезне чикләгән булырга да мөмкиннәр.\nСезнең IP адресы — $3, тыю идентификаторы — #$5.\nХатларда бу мәгълүматны күрсәтергә онытмагыз.",
        "special-characters-group-ipa": "ХФӘ (IPA)",
        "special-characters-group-symbols": "Тамгалар",
        "special-characters-group-greek": "Грек",
+       "special-characters-group-greekextended": "Грек (киңәйтелгән)",
        "special-characters-group-cyrillic": "Кирилл",
        "special-characters-group-arabic": "Гарәп",
+       "special-characters-group-arabicextended": "Гарәп (киңәйтелгән)",
        "special-characters-group-persian": "Фарсы",
        "special-characters-group-hebrew": "Яхүд",
        "special-characters-group-bangla": "Бенгаль",
-       "special-characters-group-tamil": "Тамиль",
+       "special-characters-group-tamil": "Тамил",
        "special-characters-group-telugu": "Телугу",
-       "special-characters-group-sinhala": "Сингаль",
+       "special-characters-group-sinhala": "Сингал",
        "special-characters-group-gujarati": "Гуҗарати",
        "special-characters-group-devanagari": "Деванагари",
-       "special-characters-group-thai": "Таиланд",
+       "special-characters-group-thai": "Тай",
        "special-characters-group-lao": "Лаос",
        "special-characters-group-khmer": "Кһмер"
 }
index e43f63a..52ff9c3 100644 (file)
        "create-this-page": "Та бамез кылдытыны",
        "delete": "Быдтыны",
        "deletethispage": "Та бамез быдтыны",
-       "undeletethispage": "Та Ð±Ð°Ð¼ÐµÐ· Ð±Ñ\8bдÑ\82Ñ\8bнÑ\8b",
+       "undeletethispage": "Ð\91еÑ\80ен Ñ\81Ñ\91Ñ\82Ñ\8bнÑ\8b Ñ\82а Ð±Ð°Ð¼ÐµÐ·",
        "protect": "Утьыны",
        "protect_change": "воштыны",
        "protectthispage": "Та бамез утьыны",
        "categorypage": "Категорилэсь бамзэ учкыны",
        "viewtalkpage": "Вераськонэз учкыны",
        "otherlanguages": "Мукет кылъёсын",
-       "redirectedfrom": "(Ð\9fеÑ\80енапÑ\80авлÑ\8fÑ\82Ñ\8c $1)",
+       "redirectedfrom": "(ЫÑ\81Ñ\82Ñ\8dмÑ\8bн Â«$1» Ð±Ð°Ð¼Ñ\8bÑ\81Ñ\8c)",
        "redirectpagesub": "Ыстӥсь бам",
-       "redirectto": "Ð\92Ñ\8bжÑ\8bÑ\82он:",
+       "redirectto": "ЫÑ\81Ñ\82он Ð±Ð°Ð¼Ðµ:",
        "lastmodifiedat": "Та бамлэн берпуметӥ воштонэз: $2, $1.",
        "protectedpage": "Утем бам",
        "jumpto": "Выжон:",
        "portal-url": "Project:Портал сообщества",
        "privacy": "Конфиденциальностья политика",
        "privacypage": "Project:Конфиденциальностья политика",
-       "badaccess": "ЯнгÑ\8bÑ\88Ñ\8aÑ\91Ñ\81 Ñ\8eаÑ\81Ñ\8cке",
-       "badaccess-group0": "Ð\91Ñ\8bдÑ\8dÑ\81Ñ\82Ñ\8dм Ñ\83жез Ñ\82онÑ\8d Ñ\83г Ð»Ñ\8dзÑ\8cÑ\8b, ÐºÐ¸Ð½ Ñ\82онÑ\8d ÐºÑ\83Ñ\80озы.",
-       "badaccess-groups": "УжÑ\8aÑ\91Ñ\81Ñ\8bн Ð½Ð¾, ÐºÑ\83даз Ñ\82ӥледÑ\8bз ÐºÑ\83Ñ\80иÑ\81Ñ\8cко Ð¿Ð¾Ñ\86иенÑ\82 {{PLURAL:$2|Ñ\82Ñ\83Ñ\80кÑ\8bм|гÑ\80Ñ\83ппа Ð¾Ð´Ó¥Ð³}}: $1.",
-       "versionrequired": "MediaWiki доллар кулэ версия $1",
+       "badaccess": "Ð\9bÑ\8dзÑ\91н Ñ\8fнгÑ\8bÑ\88",
+       "badaccess-group0": "Тӥ Ñ\83д Ð±Ñ\8bгаÑ\82Ó¥Ñ\81Ñ\8cке Ñ\82ӥледÑ\8bн ÐºÑ\83Ñ\80ем Ñ\83жез Ð±Ñ\8bдÑ\8dÑ\81Ñ\8aÑ\8fны.",
+       "badaccess-groups": "Ð\9aÑ\83Ñ\80ем Ñ\83жез Ð±Ñ\8bдÑ\8dÑ\81Ñ\8aÑ\8fнÑ\8b Ð±Ñ\8bгаÑ\82о {{PLURAL:$2|1=«$1» Ð³Ñ\80Ñ\83ппаÑ\8bÑ\81Ñ\8c Ð²Ð¸ÐºÐ¸Ð°Ð²Ñ\82оÑ\80Ñ\8aÑ\91Ñ\81 Ð³Ð¸Ð½Ñ\8d\82а Ð³Ñ\80Ñ\83ппаоÑ\81 Ð¿Ó§Ð»Ñ\8bÑ\81Ñ\8c Ð¾Ð³ÐµÐ·Ð»Ñ\8dн Ð²Ð¸ÐºÐ¸Ð°Ð²Ñ\82оÑ\80Ñ\8aÑ\91Ñ\81Ñ\8bз Ð³Ð¸Ð½Ñ\8d: $1}}.",
+       "versionrequired": "$1 номеро MediaWiki версия кулэ",
        "ok": "OK",
        "retrievedfrom": "«$1»-лэсь басьтэмын",
        "editsection": "тупатыны",
        "hidetoc": "ватоно",
        "collapsible-collapse": "ватоно",
        "collapsible-expand": "возьматоно",
-       "confirmable-yes": "Ð\9cед",
+       "confirmable-yes": "Ð\91ен",
        "confirmable-no": "Ӧвӧл",
        "viewdeleted": "Учкыны $1",
        "site-rss-feed": "$1 — RSS-лента",
        "createacct-yourpasswordagain": "Пароль юнматэ",
        "createacct-yourpasswordagain-ph": "Гожтэ паролез эшшо одӥг пол",
        "userlogin-remembermypassword": "Кылем сӧзнэтэз",
-       "cannotcreateaccount-title": "Уг быгатиськы гожъян кылдӥз учётной",
+       "cannotcreateaccount-title": "Учётной записьёсты кылдытыны уг луы",
        "yourdomainname": "Тӥ доменэн:",
        "login": "Пырыны",
        "nav-login-createaccount": "Нимдэс вераны / Регистрациез ортчытыны",
        "createacct-benefit-body3": "{{PLURAL:$1|викиавтор}} берло дыре",
        "loginerror": "Янгышъёс пырон",
        "createacct-error": "Янгышъёс бордын учётной книга кылдытыны",
-       "createaccounterror": "Уг быгатиськы гожъян учётной кылдоз: $1",
-       "nocookiesnew": "Ð\9aнига ÐºÑ\8bлдÑ\8bÑ\82Ñ\8bнÑ\8b Ñ\83Ñ\87Ñ\91Ñ\82ной Ð¿Ð¾Ð»Ñ\8cзоваÑ\82елÑ\8c Ð²Ð°Ð», Ð½Ð¾Ñ\88 Ñ\81иÑ\81Ñ\82ема Ñ\82он Ñ\83д Ð¿Ñ\8bÑ\80Ñ\8b.\n{{SITENAME}} Ð¿Ð¾Ð»Ñ\8cзоваÑ\82елÑ\8c cookies Ð¿Ñ\8bÑ\80он Ð¿Ð¾Ð½Ð½Ð° ÐºÑ\83Ñ\82Ñ\8bнÑ\8b.\nDisconnect cookies Ñ\82онÑ\8d Ð´Ð¾Ñ\80ам.\nÐ\9fожалÑ\83йÑ\81Ñ\82а, Ñ\81о Ð³Ð¾Ð¶Ñ\82Ó¥Ñ\81Ñ\8cке, Ð½Ð¾Ñ\88 Ñ\81обеÑ\80е Ð²Ñ\8bлÑ\8cÑ\8bÑ\81Ñ\8c Ð¿Ñ\8bÑ\80Ñ\8bнÑ\8b Ð»Ð¾Ð³Ð¸Ð½ Ð½Ð¾ Ð¿Ð°Ñ\80олÑ\8c.",
+       "createaccounterror": "Учётной запись кылдытыны уг луы: $1",
+       "nocookiesnew": "Ð\92икиавÑ\82оÑ\80 Ñ\80егиÑ\81Ñ\82Ñ\80иÑ\80оваÑ\82Ñ\8c ÐºÐ°Ñ\80емÑ\8bн, Ð½Ð¾Ñ\88 Ñ\82Ó¥ Ñ\81айÑ\82Ñ\8d Ó§Ð´ Ð¿Ñ\8bÑ\80елÑ\8d.\n{{SITENAME}} Â«cookies» Ñ\83же ÐºÑ\83Ñ\82Ñ\8d Ð²Ð¸ÐºÐ¸Ð°Ð²Ñ\82оÑ\80Ñ\8aÑ\91Ñ\81Ñ\82Ñ\8b Ñ\81айÑ\82Ñ\8d Ð»Ñ\8dзÑ\8cÑ\8bлÑ\8bнÑ\8b Ð²Ñ\8bлÑ\8bÑ\81Ñ\8c.\nТӥлÑ\8fд Â«cookies-Ñ\82Ñ\8b» Ó§Ð²Ó§Ð».\nТаÑ\83на Ð»Ñ\8dзе Ñ\81ооÑ\81Ñ\82Ñ\8b, Ñ\81обеÑ\80е Ð¿Ñ\8bÑ\80е Ñ\81айÑ\82Ñ\8d Ð°Ñ\81Ñ\8cÑ\82Ñ\8dлÑ\8dн Ð²Ñ\8bлÑ\8c Ð²Ð¸ÐºÐ¸Ð°Ð²Ñ\82оÑ\80 Ð½Ð¸Ð¼ÐµÐ½Ñ\8bдÑ\8b Ð½Ð¾ Ð¿Ð°Ñ\80оленÑ\8bдÑ\8b.",
        "nocookieslogin": "{{SITENAME}} пользователь cookies пырон понна кутыны.\nDisconnect cookies тонэ дорам.\nПожалуйста, соосты утчано, выльысь гожтыны.",
        "blocked-mailpassword": "Тон IP-адрес заблокировать-ысь редактировать карон. Злоупотребление предотвращение понна, та понна кутыны ӧз лэзиське пароль-ысь восстановление IP-адрес.",
        "loginlanguagelabel": "Кыл: $1",
        "showpreview": "Бамез эскерон",
        "showdiff": "Пыртэм воштонъёс",
        "anoneditwarning": "<strong>Сак луэ!</strong> Тӥ сайтэ ӧд пырелэ. Тӥ котькыӵе тупатонъёсыз лэсьтоды бере, тӥляд IP-адресты ваньмызлы адӟытӥськоз. Тӥ <strong>[$1 пыроды]</strong> яке <strong>[$2 учётной записез кылдытоды]</strong> бере, тӥляд тупатонъёсты герӟаськозы нимдылы, мукет пайдаосын ӵош.",
-       "blockedtitle": "Ð\97аблокиÑ\80оваÑ\82Ñ\8c Ð¿Ñ\8bÑ\80иÑ\81Ñ\8cкиÑ\81Ñ\8cÑ\91Ñ\81",
+       "blockedtitle": "Ð\92икиавÑ\82оÑ\80 Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ\80оваÑ\82Ñ\8c ÐºÐ°Ñ\80емÑ\8bн",
        "blockedtext": "<strong>Тӥляд учётной записьты яке IP-адресты заблокировать каремын вал.</strong>\n\nБлокировкаез лэсьтӥз $1.\nПусъем мугез: <em>$2</em>.\n\n* Блокировка кутскиз: $8\n* Блокировка йылпумъяськоз: $6\n* Блокировкалэн ужпумез: $7\n\nТӥ блокировка сярысь вераськыны быгатӥськоды $1 яке котькин мукет [[{{MediaWiki:Grouppage-sysop}}|администратор]] доры герӟаськыса.\n[[Special:Preferences|Настройкаосады]] электрон почталэн ужась адресэз ӧвӧл дыръя, тӥ «Викиавторлы гожтэт» функциез уже кутыны уд быгатӥське, сое тӥленыды уже кутон дугдытэмын ӧвӧл ке.\nТӥляд али IP-адресты луэ $3, но блокировка идентификатор — #$5.\nТауна пыртэ вань та пыр-поч сведениосыз асьтэлэн куронъёсады.",
        "autoblockedtext": "Тӥляд IP-адресты автоматически заблокировать каремын вал, малы ке шуоно со кутӥськиз вал мукет викиавторен, кинзэ $1 заблокировать кариз.\nБлокировкалэн пусъем мугез:\n\n:<em>$2</em>\n\n* Блокировка кутскиз: $8\n* Блокировка йылпумъяськоз: $6\n* Блокировкалэн ужпумез: $7\n\nТӥ блокировка сярысь вераськыны быгатӥськоды $1 яке мукет [[{{MediaWiki:Grouppage-sysop}}|администраторъёс]] пӧлысь огез доры герӟаськыса.\n\nСак луэ, тӥ «Викиавторлы гожтэт» функциез уже кутыны уд быгатӥське [[Special:Preferences|асьтэлэн настройкаосады]] электрон почталэсь шонер адрессэ гожтытозь яке юнматытозь, либо блокировкады сыӵе амалэн гожтэтъёсыз ыстыны уг лэзьы ке.\n\nТӥляд али IP-адресты луэ $3, но блокировка идентификатор — #$5.\nТауна пыртэ вань та пыр-поч сведениосыз асьтэлэн куронъёсады.",
-       "blockednoreason": "мÑ\83гезлÑ\8b Ñ\8dн Ð²Ð¾Ð·Ñ\8cмалÑ\8d",
+       "blockednoreason": "пÑ\83кÑ\82Ñ\8dм Ð¼Ñ\83г Ó§Ð²Ó§Ð»",
        "whitelistedittext": "Тон кулэ $1 бам воштон понна.",
        "loginreqtitle": "Авторизация кулэ",
        "loginreqlink": "пырыны",
        "newarticletext": "Тон бам ссылкаос вылэ выжыса, со кема уз улы.\nСоос мед кылдозы, текст бичась укноос, улазы интыяськемын (умой-умой см. [$1 бам справочной]).\nЯнгыш-а тон татын луысалыд ке, кнопказэ зӥбиз гинэ <strong>берлань</strong> асьтэлэсь браузеръёстэс.",
        "noarticletext": "Али дыре та бамын текст ӧвӧл. \nТӥ быгатоды [[Special:Search/{{PAGENAME}}|шедьтыны со сярысь кыӵе ке ивор]] мукет бамъёсысь,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} шедьтыны журналъёсысь гожъямъёсыз], \nяке [{{fullurl:{{FULLPAGENAME}}|action=edit}} сыӵе нимын бам кылдытыны]</span>.",
        "noarticletext-nopermission": "Али дыре та бам вылын кылкуэт ӧвӧл.\nТон быгатӥськод [[Special:Search/{{PAGENAME}}|сётэм йыръянъёс шедьто упоминание]] мукет бам вылын,\nяке <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} соответствующий журнал книгаез шедьтыны].</span> Тӥ дорын сётӥське юаськыны кылдӥз бам ӧвӧл.",
-       "blocked-notice-logextract": "Ð\9fолÑ\8cзоваÑ\82елÑ\8c Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ\80ован Ñ\81Ñ\91Ñ\82ӥз Ñ\82а Ñ\83Ñ\87Ñ\8bÑ\80лÑ\8b.\nСпÑ\80авка Ð¿Ð¾Ð½Ð½Ð° Ñ\80адÑ\8aÑ\8fÑ\81Ñ\8cкÑ\8bлӥÑ\81Ñ\8c Ð¶Ñ\83Ñ\80нал Ð±Ð»Ð¾ÐºÐ¸Ñ\80овка Ð»Ð°Ð¿ÐµÐ³ Ð±ÐµÑ\80пÑ\83меÑ\82Ó¥ Ð³Ð¾Ð¶Ñ\82Ñ\8dÑ\82:",
+       "blocked-notice-logextract": "Та Ð²Ð¸ÐºÐ¸Ð°Ð²Ñ\82оÑ\80 Ð°Ð»Ð¸ Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ\80оваÑ\82Ñ\8c ÐºÐ°Ñ\80емÑ\8bн.\nÐ\91локиÑ\80овкаоÑ\81Ñ\8bн Ð¶Ñ\83Ñ\80налÑ\8bÑ\81Ñ\8c Ð±ÐµÑ\80пÑ\83м Ð³Ð¾Ð¶Ñ\8aÑ\8fм Ñ\83лӥ Ð²Ð¾Ð·Ñ\8cмаÑ\82Ñ\8dмÑ\8bн:",
        "continue-editing": "Тупатъянэз азьланьтоно",
        "editing": "Тупатон: $1",
        "creating": "«$1» бамез кылдытон",
        "moveddeleted-notice": "Та бам быдтэмын вал.\nБыдтонъёсын но ним воштонъёсын журналъёсысь ярано записьёс чӧлсконлы улӥ возьматэмын.",
        "content-model-wikitext": "викитекст",
        "undo-summary": "Шонертон вошъян $1, лэсьтӥзы {{GENDER:$2|участник|куакеч}} [[Special:Contributions/$2|$2]] ([[User talk:$2|обс.]])",
-       "cantcreateaccount-text": "Та книгаез кылдытонлы учётной IP-адрес (<strong>$1</strong>) заблокировать луизы [[User:$3|$3]].\n\nМугез, вайиз $3 возьматэ <em>$2</em>",
-       "cantcreateaccount-range-text": "Учётной кылдытон - гожъян IP-адрес диапазонын <strong>$1</strong>, Тон пыриське со IP-адрес (<strong>$4</strong>), заблокировать луизы [[User:$3|$3]].\n\nМугез, вайиз $3 возьматэ <em>$2</em>",
+       "cantcreateaccount-text": "Та IP-адресысь (<strong>$1</strong>) учётной записьёсты кылдытон заблокировать каремын вал [[User:$3|$3]] викиавторен.\n\n$3 пусйиз таӵе мугез: <em>$2</em>.",
+       "cantcreateaccount-range-text": "[[User:$3|$3]] викиавтор дугдытӥз учётной записьёсты кылдытыны <strong>$1</strong> радлэн IP-адресъёсысьтыз, кудъёсыз пӧлы пыре тӥляд IP-адресты (<strong>$4</strong>).\n\n$3 пусйиз таӵе мугез: <em>$2</em>.",
        "viewpagelogs": "Та бамлы журналъёсыз возьматыны",
        "currentrev-asof": "Алиез версия $1",
        "revisionasof": "Версия $1",
        "categories-submit": "Возьматыны",
        "sp-deletedcontributions-contribs": "тупатонъёсыз",
        "listusers-submit": "Возьматыны",
-       "listusers-blocked": "(заблокиÑ\80оваÑ\82Ñ\8c{{GENDER:$1||а}})",
+       "listusers-blocked": "(блокиÑ\80оваÑ\82Ñ\8c ÐºÐ°Ñ\80емÑ\8bн)",
        "listgrouprights": "Право группае пыриськисьёс",
        "listgrouprights-summary": "Та группае пырисьёс возьматыны кулэ вики список улӥзы, право соответствующийгес солы возьматоно кариськиз. Оло, ас [[{{MediaWiki:Listgrouprights-helppage}}|кожазы ватсаса ивортодэт]] улыны эрикрадэз сярысь.",
        "listgrouprights-members": "(список пыриськисьёс)",
        "whatlinkshere-hidetrans": "$1 пыртонъёсты",
        "whatlinkshere-hidelinks": "$1 чӧлсконъёсты",
        "whatlinkshere-filters": "Фильтръёс",
-       "block": "Блокировка пыриськисьёс",
-       "blockip": "Заблокировать {{GENDER:$1|пыриськисьёс}}",
+       "block": "Викиавторез заблокировать карыны",
+       "blockip": "{{GENDER:$1|Викиавторез}} заблокировать карыны",
+       "blockip-legend": "Блокировка пыриськисьёс",
+       "blockiptext": "Формазэ уже кутыса, кулэ луэмезъя мед заблокировать гожъян IP-адрес яке пыриськисьёслэн нимъёссы.\nТа понна гинэ но соя гинэ лэсьтэмын луыны быгатоз вандализм предотвращение с [[{{MediaWiki:Policy-url}}|правилоосты]].\nМугез возьматись улӥзы членъёсын (кылсярысь, куд-ог тодметъёссэ вандализм цитировать кароно бам).\nТӥ быгатӥськоды диапазонэз заблокировать IP-адрес, уже кутыны [https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing CIDR]-синтаксис. Максимально диапазонэз допустимый — /$1 протокол понна IPv4 но /$2 протокол понна IPv6.",
        "ipbreason-dropdown": "* Блокировка мугез кабес\n** Полы информациез оскизы\n** Вордскем палэнэ бам\n** Спам-сайтъя педпал чӧлскон\n** Текстлэсь визьем ватсан/жуг-жаг\n** Кышкытлыклэсь, пыриськыны уйиськон\n** Злоупотребление кӧня ке книга учётной\n** Пыриськисьёслэн нимъёссы пыриськисьёс",
+       "ipbsubmit": "Адресъёсын та заблокировать/пыриськисьёс",
        "ipboptions": "2 час:2 hours,1 нуналлы:1 day,3 нуналлы:3 days,1 арняезлы:1 week,2 арняяз:2 weeks,1 толэзь:1 month,3 толэзь:3 months,6 толэзь:6 months,1 арлэн:1 year,ноку:infinite",
        "ipb-blocklist-contribs": "{{GENDER:$1|$1}} гожтэмъёсы",
-       "unblocked": "[[User:$1|$1]] разблокировать",
-       "unblocked-id": "Блокировка $1 басьтоно луиз",
-       "blocklist-target": "Ужпумъёс",
+       "unblocked": "[[User:$1|$1]] разблокировать каремын.",
+       "unblocked-id": "$1 номеро блокировка палэнтэмын вал.",
+       "blocklist-target": "Ужпумез",
        "blocklist-reason": "Мугез",
        "infiniteblock": "ноку",
        "expiringblock": "йылпумъяськиз $1-ысь $2",
        "contribslink": "тупатонъёсыз",
        "autoblocker": "Автоблокировка, малы ке шуоно «[[User:$1|$1]]» тӥлесьтыд IP-адрестэс алигес уже кутӥз.\n$1 блокировкалэн мугез: «$2»",
        "blocklogpage": "Блокировкаосын журнал",
-       "blocklogentry": "заблокировать [[$1]] дыр $2 $3",
-       "reblock-logentry": "блокиÑ\80овка Ð²Ð¾Ñ\88Ñ\82ӥз [[$1]] Ð´Ñ\8bÑ\80 $2 $3",
-       "blocklogtext": "Ð\91локиÑ\80овка Ð½Ð¾ Ñ\82а Ð¶Ñ\83Ñ\80наллÑ\8dн Ñ\83жезлÑ\8b Ñ\80азблокиÑ\80ование Ð¿Ð¾Ð»Ñ\8cзоваÑ\82елÑ\8c.\nÐ\97аблокиÑ\80оваÑ\82Ñ\8c Ð\90вÑ\82омаÑ\82иÑ\87еÑ\81ки IP-адÑ\80еÑ\81 Ñ\83г Ð²Ð¾Ð·Ñ\8cма.\nÐ\9fÑ\80оизведениоÑ\81Ñ\8bз Ð¿ÐµÑ\87аÑ\82лаÑ\81Ñ\8cко Ñ\8dÑ\81Ñ\82ониÑ\8bн [[Special:BlockList|Ñ\81Ñ\8cӧд Ñ\81пиÑ\81окÑ\8bн]], Ð±Ð°Ð½ Ñ\81пиÑ\81ок Ð±Ð»Ð¾ÐºÑ\8aÑ\91Ñ\81 Ð»Ñ\8dÑ\81Ñ\8cÑ\82Ñ\8bнÑ\8b.",
-       "unblocklogentry": "разблокировать $1",
+       "blocklogentry": "заблокировать кариз [[$1]] дырлы: $2 $3",
+       "reblock-logentry": "воÑ\88Ñ\82ӥз Ð±Ð»Ð¾ÐºÐ¸Ñ\80овкалÑ\8dÑ\81Ñ\8c Ð¹Ñ\8bлпÑ\83мÑ\8aÑ\8fнзÑ\8d [[$1]] Ð¿Ð¾Ð½Ð½Ð° Ð´Ñ\8bÑ\80лÑ\8b: $2 $3",
+       "blocklogtext": "Ð\92икиавÑ\82оÑ\80Ñ\8aÑ\91Ñ\81Ñ\82Ñ\8b Ð±Ð»Ð¾ÐºÐ¸Ñ\80овкаоÑ\81Ñ\8bн Ð½Ð¾ Ñ\80азблокиÑ\80овкаоÑ\81Ñ\8bн Ð¶Ñ\83Ñ\80нал.\nÐ\90вÑ\82омаÑ\82иÑ\87еÑ\81ки Ð±Ð»Ð¾ÐºÐ¸Ñ\80оваÑ\82Ñ\8c ÐºÐ°Ñ\80иÑ\81Ñ\8cкиÑ\81Ñ\8c IP-адÑ\80еÑ\81Ñ\8aÑ\91Ñ\81 Ñ\82аÑ\82Ñ\8bн Ñ\83г Ð°Ð´Ó\9fÑ\8bÑ\82Ó¥Ñ\81Ñ\8cко.\nУÑ\87ке [[Special:BlockList|Ñ\81пиÑ\81окез Ð°Ð»Ð¸ ÐºÑ\83Ñ\82Ó¥Ñ\81Ñ\8cкиÑ\81Ñ\8c Ð±Ð»Ð¾ÐºÐ¸Ñ\80овкаоÑ\81лÑ\8b]].",
+       "unblocklogentry": "разблокировать кариз $1",
        "block-log-flags-anononly": "пользователь гинэ нимтултэм",
        "block-log-flags-nocreate": "регистрация учётной книгая ужъёсты быдэстон",
        "block-log-flags-noemail": "лэзьымтэ гожтэт ыстон",
        "block-log-flags-nousertalk": "тупатъяны ачиз уггес быгаты бамлэн обсуждениосаз",
-       "range_block_disabled": "Администратор диапазонэз блокировать али.",
+       "range_block_disabled": "Администраторъёслэн диапазонъёсыз блокировать карыны луонлыксы дугдытэмын.",
        "move-watch": "Чаклан списоке пыртоно инъет но валтӥсь бамъёсыз",
        "movelogpage": "Нимъёсты воштонъёсын журнал",
        "export": "Бамъёсты поттон",
        "logentry-delete-delete": "$1 {{GENDER:$2|палэнтыны|палэнтыны}} бам $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|выльысь}} бам $3",
        "logentry-block-block": "$1 {{GENDER:$2|заблокировать}} {{GENDER:$4|$3}} ын дыраз $5 $6",
+       "logentry-block-reblock": "$1 {{GENDER:$2|воштыны}} блокировка дыръя {{GENDER:$4|$3}} ын дыраз $5 $6",
+       "logentry-suppress-block": "$1 {{GENDER:$2|заблокировать}} {{GENDER:$4|$3}} ын дыраз $5 $6",
+       "logentry-suppress-reblock": "$1 {{GENDER:$2|воштыны}} блокировка дыръя {{GENDER:$4|$3}} ын дыраз $5 $6",
        "logentry-move-move": "$1 $3 бамлы $4 выль ним {{GENDER:$2|сётӥз}}",
        "logentry-newusers-create": "$1 нимо учётной запись {{GENDER:$2|кылдытэмын}} вал",
        "logentry-upload-upload": "$1 {{GENDER:$2|понӥз}} $3",
        "searchsuggest-search": "Утчано {{SITENAME}}",
        "searchsuggest-containing": "кудъёсаз вань...",
-       "api-error-autoblocked": "Тон IP-адрес заблокировать эрказ луи, малы ке шуоно со заблокировать пользователь кутыны луоз.",
-       "api-error-blocked": "РедакÑ\82иÑ\80ование Ð·Ð°Ð±Ð»Ð¾ÐºÐ¸Ñ\80оваÑ\82Ñ\8c Ð²Ð°Ð» Ñ\82ӥлеÑ\81Ñ\8cÑ\82Ñ\8bд.",
+       "api-error-autoblocked": "Тӥляд IP-адресты автоматически заблокировать каремын вал, малы ке шуоно со кутӥськиз заблокировать карем викиавторен.",
+       "api-error-blocked": "Тӥ Ñ\82Ñ\83паÑ\82Ñ\8aÑ\8fнлÑ\8dÑ\81Ñ\8c Ð¿Ð°Ð»Ñ\8dнÑ\82Ñ\8dмÑ\8bн Ð²Ð°Ð».",
        "expand_templates_preview": "Эскерон",
        "log-action-filter-all": "Ваньзэ"
 }
index 96edbf9..a638005 100644 (file)
        "toolbox": "Інструменти",
        "tool-link-userrights": "Змінити групи {{GENDER:$1|користувачів}}",
        "tool-link-userrights-readonly": "Перегляд груп {{GENDER:$1|користувача|користувачки}}",
-       "tool-link-emailuser": "Ð\9dадÑ\96Ñ\81лаÑ\82и ÐµÐ»ÐµÐºÑ\82Ñ\80онного Ð»Ð¸Ñ\81Ñ\82а {{GENDER:$1|Ñ\86Ñ\8cомÑ\83 ÐºÐ¾Ñ\80иÑ\81Ñ\82Ñ\83ваÑ\87евÑ\96\86Ñ\96й користувачці}}",
+       "tool-link-emailuser": "Ð\9bиÑ\81Ñ\82 {{GENDER:$1|коÑ\80иÑ\81Ñ\82Ñ\83ваÑ\87евÑ\96|користувачці}}",
        "userpage": "Переглянути сторінку користувача",
        "projectpage": "Переглянути сторінку проекту",
        "imagepage": "Переглянути сторінку файлу",
        "blockedtitle": "Користувача заблоковано",
        "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\nЗверніть увагу, що ви не зможете надіслати листа адміністратору, якщо ви не зареєстровані або не підтвердили свою електронну адресу в [[Special:Preferences|особистих налаштуваннях]], а також якщо вам було заборонено надсилати листи при блокуванні.\n\nВаша поточна IP-адреса — $3, ідентифікатор блокування — #$5. Будь ласка, зазначайте ці дані у своїх запитах.",
        "autoblockedtext": "Ваша IP-адреса автоматично заблокована у зв'язку з тим, що вона раніше використовувалася кимось із заблокованих користувачів. Адміністратор ($1), що її заблокував, зазначив наступну причину блокування:\n\n:''$2''\n\n* Початок блокування: $8\n* Закінчення блокування: $6\n* Блокування виконав: $7\n\nВи можете надіслати листа користувачеві $1 або будь-якому іншому [[{{MediaWiki:Grouppage-sysop}}|адміністратору]], щоб обговорити блокування.\n\nЗверніть увагу, що ви не зможете надіслати листа адміністраторові, якщо ви не зареєстровані у проекті або не підтвердили свою електронну адресу в [[Special:Preferences|особистих налаштуваннях]], а також якщо вам було заборонено надсилати листи при блокуванні.\n\nВаша поточна IP-адреса — $3, ідентифікатор блокування — #$5. Будь ласка, зазначайте його у своїх запитах.",
+       "systemblockedtext": "Ваше ім'я користувача або IP-адресу було автоматично заблоковано MediaWiki.\nВказана причина:\n\n:<em>$2</em>\n\n* Початок блокування: $8\n* Закінчення блокування: $6\n* Ціль блокування: $7\n\nВаша поточна IP-адреса — $3.\nБудь ласка, додайте всі вказані подробиці до будь-яких запитів, які Ви будете робити.",
        "blockednoreason": "не вказано причини",
        "whitelistedittext": "Ви повинні $1, щоб редагувати сторінки.",
        "confirmedittext": "Ви повинні підтвердити вашу адресу електронної пошти перед редагуванням сторінок.\nБудь-ласка вкажіть і підтвердіть вашу електронну адресу на [[Special:Preferences|сторінці налаштувань]].",
        "pageinfo-length": "Довжина сторінки (в байтах)",
        "pageinfo-article-id": "ID сторінки",
        "pageinfo-language": "Мова вмісту сторінки",
+       "pageinfo-language-change": "Змінити",
        "pageinfo-content-model": "Модель вмісту сторінки",
        "pageinfo-content-model-change": "змінити",
        "pageinfo-robot-policy": "Індексація пошуковими системами",
        "restrictionsfield-badip": "Недійсна IP-адреса або діапазон: $1",
        "restrictionsfield-label": "Дозволені діапазони IP-адрес:",
        "restrictionsfield-help": "Одна IP-адреса або CIDR-діапазон на рядок. Щоб увімкнути все, використайте<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "версія $1",
        "pageid": "ID сторінки $1"
 }
index 5197c00..5f342a8 100644 (file)
@@ -50,7 +50,7 @@
        "tog-enotifminoredits": "頁搭文件細編也用電子信通知我",
        "tog-enotifrevealaddr": "電子信通知單裏顯示我個電子信地址",
        "tog-shownumberswatching": "顯示關注人數",
-       "tog-oldsig": "原生个签名:",
+       "tog-oldsig": "原生个签名:",
        "tog-fancysig": "拿签名当成维基文本(弗自动链接)",
        "tog-uselivepreview": "使用实时预览",
        "tog-forceeditsummary": "朆写编辑摘要个辰光提醒我",
        "newwindow": "(用新窗口开)",
        "cancel": "取消",
        "moredotdotdot": "還多...",
-       "morenotlisted": "ç®\87張表é\82\84æ\9c\86å®\8cæ\88\90。",
+       "morenotlisted": "ç®\87å¼ æ¸\85å\8d\95ä½\9cå\85´å¼\97å®\8cæ\95´。",
        "mypage": "页面",
        "mytalk": "讲张",
        "anontalk": "讲张",
        "botpasswords-label-create": "建立",
        "botpasswords-label-update": "更新",
        "resetpass_forbidden": "密码弗好更改",
+       "resetpass_forbidden-reason": "密码弗好更改:$1",
        "resetpass-no-info": "侬必须登录著才好直接进入箇只页面。",
        "resetpass-submit-loggedin": "更改密码",
        "resetpass-submit-cancel": "取消",
        "resetpass-expired": "侬个密码到期哉。请设置新个登录密码。",
        "passwordreset": "重置密码",
        "passwordreset-username": "用戶名",
-       "passwordreset-capture": "啊要看生成个电子邮件?",
        "passwordreset-email": "电子邮件地址:",
        "passwordreset-emailtitle": "{{SITENAME}}上个账号详细信息",
        "passwordreset-emailelement": "用户名:\n$1\n\n临时密码:\n$2",
        "minoredit": "箇是小变化",
        "watchthis": "关注箇页",
        "savearticle": "保存页面",
+       "savechanges": "保存改动",
+       "publishpage": "发布页面",
+       "publishchanges": "发布改动",
        "preview": "望望相",
        "showpreview": "显示预览",
        "showdiff": "显示变化",
        "searchprofile-advanced-tooltip": "垃拉自定义名字空间里向搜索",
        "search-result-size": "$1($2个字)",
        "search-result-category-size": "$1个成员($2个儿分类,$3个文件)",
-       "search-redirect": "(重定向 $1)",
+       "search-redirect": "(从$1重定向过来)",
        "search-section": "(段落 $1)",
        "search-category": "(分类$1)",
        "search-file-match": "(匹配文件内容)",
        "recentchangescount": "默认显示个编辑数:",
        "prefs-help-recentchangescount": "迭个包括近段辰光个改动、页面历史搭著日志。",
        "savedprefs": "倷个偏好已经保存哉。",
-       "savedrights": "{{GENDER:$1|$1}}个用户权限已经畀保存。",
+       "savedrights": "{{GENDER:$1|$1}}个用户组已经保存哉。",
        "timezonelegend": "时区:",
        "localtime": "当地辰光:",
        "timezoneuseserverdefault": "使用wiki默认值($1)",
        "prefs-advancedwatchlist": "高级选项",
        "prefs-tabs-navigation-hint": "提示:侬可以用左、右箭头键来选项卡之间切换。",
        "userrights-user-editname": "输入用户名:",
-       "editusergroup": "编辑{{GENDER:$1|用户}}组",
+       "editusergroup": "加载用户组",
        "editinguser": "改动{{GENDER:$1|用户}}<strong>[[User:$1|$1]]</strong>个用户权限$2",
+       "userrights-editusergroup": "编辑用户组",
+       "userrights-viewusergroup": "望用户组",
+       "saveusergroups": "保存{{GENDER:$1|用户}}组",
+       "userrights-reason": "理由:",
        "group-bot": "机器人",
        "group-sysop": "管理员",
        "group-bureaucrat": "行政员",
        "action-reupload": "箇文件以舊換新",
        "action-upload_by_url": "從URL傳文件",
        "action-delete": "刪箇頁",
-       "action-deleterevision": "å\88ªç®\87ç\89\88æ\9c¬",
-       "action-deletedhistory": "望箇页删脱个历史",
+       "action-deleterevision": "å\88 è\84±ä¿®è®¢",
+       "action-deletedhistory": "望页面删脱个历史",
        "action-browsearchive": "尋已刪頁",
-       "action-undelete": "弗刪箇頁",
+       "action-undelete": "还原页面",
        "action-patrol": "拿别人家个编辑标记成已巡查",
        "action-userrights": "編全部用戶權",
        "action-userrights-interwiki": "編用戶徠各許維基個權",
        "brokenredirects-delete": "删除",
        "withoutinterwiki": "嘸語言鏈接個頁面",
        "withoutinterwiki-summary": "下向許頁面朆鏈接到別樣語言版本。",
+       "fewestrevisions": "版本顶少个页面",
        "nbytes": "$1字节",
        "nmembers": "$1只成员",
        "unusedimages": "朆用着个文件",
        "prefixindex": "全部带前缀个页面",
        "shortpages": "短页面",
        "longpages": "长页面",
-       "protectedpages": "受保护页面",
-       "protectedtitles": "保护个标题",
+       "protectedpages": "畀保护个页面",
+       "protectedtitles": "保护个标题",
        "listusers": "用户列表",
        "listusers-creationsort": "照建個日子排",
        "newpages": "新页",
        "ipboptions": "2个钟头:2 hours,1天:1 day,3天:3 days,1个礼拜:1 week,2个礼拜:2 weeks,1个号头:1 month,3个号头:3 months,6个号头:6 months,1年:1 year,老世:infinite",
        "badipaddress": "无效 IP 地址",
        "blockipsuccesstext": "[[Special:Contributions/$1|$1]]已经畀查封。<br />\n参看[[Special:BlockList|查封列表]]来复审查封。",
+       "blocklist": "封脱个用户",
        "ipblocklist": "封脱个用户",
        "infiniteblock": "永远",
        "blocklist-nousertalk": "弗准编辑自家个讨论页",
        "interlanguage-link-title": "̩$1 - $2",
        "anonymous": "{{SITENAME}}上个匿名{{PLURAL:$1|用户}}",
        "simpleantispam-label": "反垃圾检查。<strong>弗要</strong>填伊个!",
+       "pageinfo-title": "“$1”个信息",
+       "pageinfo-display-title": "显示题目头",
+       "pageinfo-language": "页面内容闲话",
+       "pageinfo-redirects-name": "指向箇页个重定向数目",
+       "pageinfo-firstuser": "页面建立者",
+       "pageinfo-firsttime": "页面建立日脚",
+       "pageinfo-lastuser": "阿末位编辑者",
+       "pageinfo-lasttime": "阿末趟编辑日脚",
+       "pageinfo-recent-authors": "最近作者数",
        "pageinfo-toolboxlink": "页面信息",
+       "pageinfo-contentpage": "算成内容页面",
        "deletedrevision": "拨删脱个旧修订 $1",
        "previousdiff": "←老版",
        "nextdiff": "新版→",
        "rightsnone": "(呒)",
        "revdelete-summary": "编辑摘要",
        "feedback-thanks-title": "谢谢侬!",
-       "searchsuggest-search": "搜寻",
+       "searchsuggest-search": "搜寻{{SITENAME}}",
        "pagelang-language": "闲话"
 }
index 8a9f6f1..91a3ad8 100644 (file)
@@ -46,7 +46,7 @@
        "tog-enotifminoredits": "שיקט מיר ע-פאסט אויך פֿאַר מינערדיקע רעדאַקטירונגען פֿון בלעטער",
        "tog-enotifrevealaddr": "דעק אויף מיין בליצפאסט אדרעס אין פאסט מודעות",
        "tog-shownumberswatching": "ווייזן דעם נומער פון בלאט אויפֿפאסערס",
-       "tog-oldsig": "איצטיגער אונטערשריפֿט:",
+       "tog-oldsig": "×\90×\99×\99ער ×\90×\99צ×\98×\99×\92ער ×\90×\95× ×\98ערשר×\99פֿ×\98:",
        "tog-fancysig": "באַהאַנדלן  אונטערשריפט אַלס וויקיטעקסט (אָן אויטאמאטישן לינק)",
        "tog-uselivepreview": "באניצן זיך מיט גיכער פאראויסדיגער ווייזונג",
        "tog-forceeditsummary": "ווארן מיך ווען איך לייג א ליידיג קורץ ווארט ענדערונג",
@@ -62,7 +62,7 @@
        "tog-showhiddencats": "ווײַזן באהאלטענע קאטעגאריעס",
        "tog-norollbackdiff": "נישט ווײַזן אונטערשייד נאכן אויספֿירן א צוריקדריי",
        "tog-useeditwarning": "שטעלן א ווארענונג ווען איך לאז איבער א רעדאקטירונג בלאט מיט נישט אויפגעהיטענע ענדערונגען",
-       "tog-prefershttps": "ניצט שטענדיק א זיכערע פארבינדונג ווען ארײַנגלאגירט",
+       "tog-prefershttps": "ניצט שטענדיק א זיכערע פארבינדונג ווען ארײנגלאגירט",
        "underline-always": "אייביג",
        "underline-never": "קיינמאל",
        "underline-default": "בלעטערער גרונטשטעלונג",
        "newwindow": "(עפֿנט זיך אין א נײַעם פענסטער)",
        "cancel": "אַנולירן",
        "moredotdotdot": "נאך…",
-       "morenotlisted": "די ליסטע איז נישט פֿולשטענדיק.",
+       "morenotlisted": "×\93×\99 ×\9c×\99ס×\98×¢ ×\90×\99×\96 ×\90פשר × ×\99ש×\98 ×¤Ö¿×\95×\9cש×\98×¢× ×\93×\99ק.",
        "mypage": "מיין בלאַט",
        "mytalk": "שמועס",
        "anontalk": "שמועס",
        "talk": "שמועס",
        "views": "קוקן",
        "toolbox": "געצייג",
+       "tool-link-userrights": "ענדערן {{GENDER:$1|באַניצער}} גרופעס",
+       "tool-link-userrights-readonly": "באקוקן {{GENDER:$1|באַניצער}} גרופעס",
+       "tool-link-emailuser": "שיקן {{GENDER:$1|דעם באניצער|די באניצערין}} ע־פאסט",
        "userpage": "זען באַניצער בלאַט",
        "projectpage": "זען פראיעקט בלאַט",
        "imagepage": "זען טעקע בלאט",
        "createacct-yourpasswordagain-ph": "ארײַנגעבן פאסווארט נאכאמאל",
        "userlogin-remembermypassword": "לאז מיך בלײַבן ארײַנלאגירט",
        "userlogin-signwithsecure": "ניצן זיכערן סארווער",
+       "cannotlogin-title": "קען נישט אריינלאגירן",
+       "cannotlogin-text": "אריינלגירן נישט מעגלעך.",
        "cannotloginnow-title": "קען נישט אריינלאגירן אצינד",
        "cannotloginnow-text": "אריינלאגירן נישט מעגלעך ווען מען ניצט $1.",
+       "cannotcreateaccount-title": "מען קען נישט באשאפֿן קאנטעס",
+       "cannotcreateaccount-text": "דירעקטע קאנטע־שאפֿונג נישט אקטיווירן אויף דער וויקי.",
        "yourdomainname": "אײַער געביט:",
        "password-change-forbidden": "איר קען נישט ענדערן פאסווערטער אויף דער וויקי.",
        "externaldberror": "עס איז אדער פארגעקומען אן אויטענטיקאציע דאטנבאזע פֿעלער אדער איר זענט נישט ערמעגליכט צו דערהיינטיגן אייער דרויסנדיגע קאנטע.",
        "eauthentsent": "א באשטעטיגונג ע-בריוו איז געשיקט געווארן צו דעם באשטימטן ע-פאסט אדרעס. איידער סיי וועלכע אנדערע ע-פאסט וועט ווערן געשיקט צו דער קאנטע, וועט איר דארפן פאלגן די אנווייזונגען אין דער מעלדונג כדי צו זיין זיכער אז די קאנטע איז טאקע אייערס.",
        "throttled-mailpassword": "מ'האט שוין געשיקט א בליצבריוו צוריקצושטעלן דאס פאסווארט, אין {{PLURAL:$1|דער לעצטער שעה|די לעצטע $1 שעה'ן}}. כדי צו פארמײַדן שלעכט באניצן, נאר איין פאסווארט צוריקשטעלן בליצבריוו וועט געשיקט ווערן אין {{PLURAL:$1|א שעה |$1 שעה'ן}}.",
        "mailerror": "פעלער ביים שיקן פּאָסט: $1",
-       "acct_creation_throttle_hit": "באַזוכער צו דער וויקי וואס באַניצן אייער IP אַדרעס האָבן שױן באַשאַפֿן {{PLURAL:$1|1 קאנטע|$1 קאנטעס}} במשך דעם לעצטן טאָג, דעם מאַקסימום וואָס מען ערלויבט אין דעם פעריאד.\n\nדערפֿאַר קענען באַזוכער וואס באַניצן דעם  IP אַדרעס נישט מער שאַפֿן נײַע קאָנטעס דערווײַל.",
+       "acct_creation_throttle_hit": "באַזוכער צו דער וויקי וואס באַניצן אייער IP אַדרעס האָבן שױן באַשאַפֿן {{PLURAL:$1|1 קאנטע|$1 קאנטעס}} במשך דעם לעצטן $2, דעם מאַקסימום וואָס מען ערלויבט אין דעם צייט פעריאד.\n\nדערפֿאַר קענען באַזוכער וואס באַניצן דעם  IP אַדרעס נישט מער שאַפֿן נײַע קאָנטעס דערווײַל.",
        "emailauthenticated": "אייער ע-פאסט אדרעס איז באשטעטיגט געווארן אום $2, $3.",
        "emailnotauthenticated": "אײַער ע-פאסט אדרעס איז נאכנישט באשטעטיגט. \nקיין ע-פאסט וועט נישט ווערן געשיקט פון קיין איינע פון די פאלגנדע אייגנקייטן.",
        "noemailprefs": "ספעציפֿירט אן ע־פאסט אַדרעס אין אײַער פרעפֿערענצן כדי די פֿעאיקייטן זאלן אַרבעטן.",
        "passwordreset-emaildisabled": "ע-פאסט דינסטן זענען געווארן אומאקטיווירט אויף דער דאזיקער וויקי.",
        "passwordreset-username": "באַניצער נאָמען:",
        "passwordreset-domain": "דאמען:",
-       "passwordreset-capture": "זען  דעם געשיקטן ע־בריוו?",
-       "passwordreset-capture-help": "אַז איר צייכנט דאס קעסטל, וועט מען ווײַזן דעם ע־בריוו (מיטן פראוויזארישן פאַסווארט) צו אײַך ווי אויך ווערן געשיקט צום באַניצער.",
        "passwordreset-email": "בליצפּאָסט אַדרעס:",
        "passwordreset-emailtitle": "קאנטע פרטים אין {{SITENAME}}",
        "passwordreset-emailtext-ip": "עמעצער (מסתמא איר, פון IP אדרעס $1) האט געבעטן צוריקצושטעלן אייער פאסווארט פאר {{SITENAME}} ($4). די פאלגנדע באניצער {{PLURAL:$3|קאנטע איז|קאנטעס זענען}}\nפארבונדן מיט דעם ע־פאסט אדרעס:\n\n$2\n\n{{PLURAL:$3|דאס פראוויזארישע פאסווארט|די פראוויזארישע פאסווערטער}} וועלן אויסגיין נאך {{PLURAL:$5|איין טאג|$5 טעג}}.\nאיר זאלט אריינלאגירן און קלויבן א נייע פאסווארט אצינד. טאמער א צווייטער האט געשיקט די בקשה,\nאדער ווען איר געדענקט יא אייער פריעריקע פאסווארט, און וויל עס נישט ענדערן,\n קענט איר איגנארירן דעם אנזאג און ניצן ווייטער דאס אלטע פאסווארט.",
        "searchprofile-advanced-tooltip": "זוכן אין צוגעשטעלטע ָנאָמענטיילן",
        "search-result-size": "$1 ({{PLURAL:$2|איין ווארט|$2 ווערטער}})",
        "search-result-category-size": "{{PLURAL:$1|1 מיטגליד|$1 מיטגלידער}} ({{PLURAL:$2|1 אונטער־קאַטעגאריע|$2 אונטער־קאַטעגאריעס}}, {{PLURAL:$3|1 טעקע|$3 טעקעס}})",
-       "search-redirect": "(ווײַטערפֿירן $1)",
+       "search-redirect": "(×\95×\95ײַ×\98ערפֿ×\99ר×\95× ×\92 ×¤Ö¿×\95×\9f $1)",
        "search-section": "(אפטיילונג $1)",
        "search-category": "(קאטעגאריע $1)",
        "search-file-match": "(פאסט צו טעקע אינהאלט)",
        "prefs-help-recentchangescount": "כולל לעצטע ענדערונגען, בלאַט היסטאָריעס, און לאָגביכער.",
        "prefs-help-watchlist-token2": "דאס איז דער געהיימער שליסל צום וועבפֿיד פון אײַער אויפֿפאסונג ליסטע.\nיעדער וואס ווייסט אים וועט קענען לייענען אײַער אויפֿפאסונג ליסטע; טוט אים נישט טיילן.\n[[Special:ResetTokens|קליקט דא ווען איר דארפט אים צוריקשטעלן]].",
        "savedprefs": "אייערע פרעפערענצן איז אפגעהיטן געווארן.",
-       "savedrights": "×\93×\99 ×\91×\90× ×\99צער־רע×\9b×\98×\9f פֿון {{GENDER:$1|$1}} זענען געווארן געשפייכלערט.",
+       "savedrights": "×\93×\99 ×\91×\90× ×\99צער־×\92ר×\95פעס פֿון {{GENDER:$1|$1}} זענען געווארן געשפייכלערט.",
        "timezonelegend": "צײַט זאנע:",
        "localtime": "לאקאלע צייט:",
        "timezoneuseserverdefault": "ניצן סערווירער גרונט ($1)",
        "prefswarning-warning": "איר האט געמאכט ענדערונגען צו אײַערע פרעפערענצן וואס זענען נאך נישט אויפגעהיטן.\nאז איר פארלאזט דעם בלאט אן קליקן ״$1״ וועלן אײַערע פרעפערענצן נישט ווערן דערהײַנטיקט.",
        "prefs-tabs-navigation-hint": "טיפ: איר קענט ניצן די רעכטס און לינקס פייל־קלאווישן צו נאוויגירן צווישן די צינגלעך אין דער צינגלעך־ליסטע.",
        "userrights": "באַניצער רעכטן פֿאַרוואַלטערשאפט",
-       "userrights-lookup-user": "פֿ×\90ַר×\95×\95×\90Ö·×\9c×\98×\9f ×\91×\90× ×\99צער ×\92ר×\95פעס",
+       "userrights-lookup-user": "×\90×\95×\99ס×\95×\95×\99×\99×\9c×\9f ×\90 ×\91×\90× ×\99צער",
        "userrights-user-editname": "לייגט אריין א באַניצער-נאמען:",
-       "editusergroup": "רע×\93×\90Ö·×\92×\99ר×\9f {{GENDER:$1|×\91×\90Ö·× ×\99צער}} גרופּעס",
+       "editusergroup": "×\9c×\90×\93×\9f ×\91×\90Ö·× ×\99צער גרופּעס",
        "editinguser": "ענדערן באַניצער רעכטן פון  {{GENDER:$1|באַניצער|באַניצערין}} <strong>[[User:$1|$1]]</strong> $2",
        "userrights-editusergroup": "רעדאַקטירן באַניצער גרופעס",
+       "userrights-viewusergroup": "באַקוקן באַניצער גרופעס",
        "saveusergroups": "אויפֿהיטן {{GENDER:$1|באַניצער}} גרופעס",
        "userrights-groupsmember": "מיטגליד פון:",
        "userrights-groupsmember-auto": "אויטאמטישער מיטגליד פֿון:",
        "userrights-reason": "אורזאַך:",
        "userrights-no-interwiki": "איר האט נישט קיין ערלויבניש צו רעדאַקטירן באַניצער רעכטן אויף אַנדערע וויקיס.",
        "userrights-nodatabase": "דאַטנבאַזע $1 אדער עקזיסטירט נישט אדער איז נישט ארטיק.",
-       "userrights-nologin": "איר דאַרפֿט [[Special:UserLogin| אַרײַנלאגירן]] מיט א סיסאפ קאנטע צו באַשטימען באַניצער רעכטן.",
-       "userrights-notallowed": "איר האט נישט קיין ערלויבניש צוצולייגן אדער אוועקנעמען באַניצער רעכטן.",
        "userrights-changeable-col": "גרופעס איר קענט ענדערן",
        "userrights-unchangeable-col": "גרופעס איר קענט נישט ענדערן",
        "userrights-conflict": "קאנפֿליקט פון באניצער־רעכטן ענדערונגען! זייט אזוי גוט רעצענזירן און באשטעטיקן אײַערע ענדערונגען.",
-       "userrights-removed-self": "איר האט אראפגענומען אייערע אייגענע רעכטן. אזוי קענט איר מער נישט דערגרייכן דעם בלאט.",
        "group": "גרופע:",
        "group-user": "באניצערס",
        "group-autoconfirmed": "באַשטעטיקטע באַניצער",
        "right-siteadmin": "פארשליס און שליס-אויף די דאטעבאזע",
        "right-override-export-depth": "עקספארטירן בלעטער כולל געלינקטע בלעטער ביז א טיף פון 5",
        "right-sendemail": "שיקן ע-פאסט צו אנדערע באניצער",
-       "right-passwordreset": "באַקוקן פאַסווארט צוריקשטעלן ע־בריוו",
        "right-managechangetags": "שאפן און (אומ)אקטיווירן [[Special:Tags|טאגן]]",
        "right-applychangetags": "אנווענדן [[Special:Tags|טאגן]] צוזאמען מיט ענדערונגען",
        "grant-generic": "\"$1\" רעכטן־בינטל",
        "grant-group-file-interaction": "אינטעראגירן מיט מעדיע",
        "grant-group-watchlist-interaction": "אינטעראגירן מיט אייער אויפֿפאסונג־ליסטע",
        "grant-group-email": "שיקן ע־פאסט",
+       "grant-group-other": "פֿארשידענע אקטיוויטעטן",
        "grant-createaccount": "שאַפֿן קאנטעס",
        "grant-editmywatchlist": "רעדאקטירן אײַער אויפֿפאסונג ליסטע",
        "grant-editpage": "רעדאקטירן עקזיסטירנדע בלעטער",
        "action-upload_by_url": "ארויפֿלאָדן די טעקע פֿון א URL",
        "action-writeapi": "ניצן דעם שרײַבן API",
        "action-delete": "אויסמעקן דעם בלאַט",
-       "action-deleterevision": "אויסמעקן די רעוויזיע",
-       "action-deletedhistory": "באַקוקן דעם בלאט'ס אויסגעמעקטע היסטאריע",
+       "action-deleterevision": "אויסמעקן רעוויזיעס",
+       "action-deletedhistory": "באַקוקן א בלאט'ס אויסגעמעקטע היסטאריע",
+       "action-deletedtext": "באקוקן אויסגעמעקטן רעוויזיע טעקסט",
        "action-browsearchive": "זוכן אויסגעמעקטע בלעטער",
-       "action-undelete": "צ×\95ר×\99קש×\98×¢×\9c×\9f ×\93×¢×\9d ×\91×\9c×\90×\98",
-       "action-suppressrevision": "×\90×\99×\91ער×\92×\99×\99×\9f ×\90×\95×\9f ×¦×\95ר×\99קש×\98×¢×\9c×\9f ×\93×\99 ×¤Ö¿×\90ַר×\91×\90ר×\92×\98×¢ ×¨×¢×\95×\95×\99×\96×\99×¢",
+       "action-undelete": "צ×\95ר×\99קש×\98×¢×\9c×\9f ×\91×\9c×¢×\98ער",
+       "action-suppressrevision": "×\90×\99×\91ער×\92×\99×\99×\9f ×\90×\95×\9f ×¦×\95ר×\99קש×\98×¢×\9c×\9f ×¤Ö¿×\90ַר×\91×\90ר×\92×\98×¢ ×¨×¢×\95×\95×\99×\96×\99עס",
        "action-suppressionlog": "באקוקן דעם פריוואטן לאג",
        "action-block": "בלאקירן דעם באַניצער פֿון רעדאַקטירן",
        "action-protect": "ענדערן שיצונג ניוואען פֿאַר דעם בלאַט",
        "action-userrights-interwiki": "רעדאַקטירן רעכטן פון באַניצער אויף אַנדערע וויקיס",
        "action-siteadmin": "שליסן אדער אויפשליסן די דאטנבאזע",
        "action-sendemail": "שיקן ע־פאסט",
+       "action-editmyoptions": "רעדאקטירן אײַערע פרעפערענצן",
        "action-editmywatchlist": "רעדאקטירן אײַער אויפֿפאסונג ליסטע",
        "action-viewmywatchlist": "באקוקן אײַער אויפֿפאסונג ליסטע",
        "action-viewmyprivateinfo": "באקוקן אײַער פריוואטע אינפארמאציע",
        "upload-copy-upload-invalid-domain": "ארויפלאדן טעקעס פון דעם דאמיין נישט מעגלעך.",
        "upload-dialog-title": "אַרױפֿלאָדן טעקע",
        "upload-dialog-button-cancel": "אַנולירן",
+       "upload-dialog-button-back": "צוריק",
        "upload-dialog-button-done": "ערליידיקט",
        "upload-dialog-button-save": "אויפֿהיטן",
        "upload-dialog-button-upload": "אַרויפֿלאָדן",
        "emailccsubject": "קאפיע פון אײַער מעלדונג צו $1: $2",
        "emailsent": "ע-פאסט געשיקט",
        "emailsenttext": "אײַער אי-בריוו איז געשיקט געווארן.",
-       "emailuserfooter": "דער בליצבריוו איז {{GENDER:$1|געשיקט געווארן}} דורך $1 צו {{GENDER:$2|$2}} מיט דער \"{{int:emailuser}}\" פֿונקציע בײ {{SITENAME}}.",
+       "emailuserfooter": "דער בליצבריוו איז {{GENDER:$1|געשיקט געווארן}} דורך $1 צו {{GENDER:$2|$2}} מיט דער \"{{int:emailuser}}\" פֿונקציע בײ {{SITENAME}}. {{GENDER:$2|אייער}} ע־פאסט וועט מען שיקן גראד be sent directly to the {{GENDER:$1|צום אריגינעלן אפשיקער|צו דער אריגינעלער אפשיקערין}}, וואס וועט אויפדעקן {{GENDER:$2|אייער}} ע־פאסט אדרעס צו {{GENDER:$1|אים|איר}}.",
        "usermessage-summary": "איבערלאזן סיסטעם אָנזאָג",
        "usermessage-editor": "סיסטעם שליח",
        "usermessage-template": "MediaWiki:באניצער־מעלדונג",
        "sp-contributions-newbies-title": "ביישטייערונגען פון נייע באַניצער",
        "sp-contributions-blocklog": "בלאקירן לאג",
        "sp-contributions-suppresslog": "אונטערדריקטע {{GENDER:$1|באַניצער}} בײַשטײַערונגען",
-       "sp-contributions-deleted": "אויסגעמעקטע באַניצער בײַשטײַערונגען",
+       "sp-contributions-deleted": "אויסגעמעקטע {{GENDER:$1|באַניצער|באַניצערין}} בײַשטײַערונגען",
        "sp-contributions-uploads": "אַרויפֿלאָדונגען",
        "sp-contributions-logs": "לאגביכער",
        "sp-contributions-talk": "שמועס",
        "htmlform-cloner-delete": "אַראָפּנעמען",
        "htmlform-title-not-exists": "$1 עקזיסטירט נישט",
        "logentry-delete-delete": "$1 {{GENDER:$2|האט אויסגעמעקט}} בלאט $3",
+       "logentry-delete-delete_redir": "$1 {{GENDER:$2|האט אויסגעמעקט}} ווייטערפֿירונג $3 דורך איבערשרייבן",
        "logentry-delete-restore": "$1 {{GENDER:$2|האט צוריקגעשטעלט }} בלאט $3",
        "logentry-delete-event": "$1 {{GENDER:$2|האט געענדערט}} די זעבארקייט פון {{PLURAL:$5|א לאגבוך אקטיוויטעט|$5 לאגבוך אקטיוויטעטן}} אויף $3: $4",
        "logentry-delete-revision": "$1 {{GENDER:$2|האט געענדערט}} די זעבארקייט פון  {{PLURAL:$5|א רעוויזיע|$5 רעוויזיעס}} אויף בלאט $3: $4",
        "feedback-subject": "טעמע:",
        "feedback-submit": "אײַנגעבן",
        "feedback-thanks": "ייש\"כ! אײַער פֿידבעק איז געווארן ארויפגעלעגט צום בלאט \"[$2 $1]\".",
-       "searchsuggest-search": "×\96×\95×\9a",
+       "searchsuggest-search": "×\96×\95×\9b×\9f {{SITENAME}}",
        "searchsuggest-containing": "כולל…",
        "api-error-badaccess-groups": "איר האט נישט קיין רעכטן אַרויפֿלאָדן טעקעס אויף דער וויקי.",
        "api-error-badtoken": "אינערלעכער גרײַז: סימן טויג נישט.",
index 5b9ec3d..2635dff 100644 (file)
        "subject-preview": "主题预览:",
        "previewerrortext": "尝试预览您的更改时发生未知错误。",
        "blockedtitle": "用户被封禁",
-       "blockedtext": "<strong>您的用户名或IP地址已被封禁。</strong>\n\n执行封禁的管理员是$1。封禁原因是<em>$2</em>。\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联络$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。只有当您在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才可以使用它。您当前的IP地址是$3,该封禁ID是#$5。请在您的询问中包含上面的所有信息。",
-       "autoblockedtext": "您的IP地址因曾被一位被$1封禁的用户使用而被自动封禁。封禁原因:\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请您在申诉内容中说明以上所有信息。",
+       "blockedtext": "<strong>您的用户名或IP地址已被封禁。</strong>\n\n执行封禁的管理员是$1。封禁原因是<em>$2</em>。\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您可以联络$1或其他[[{{MediaWiki:Grouppage-sysop}}|管理员]]讨论该封禁。只有当您在[[Special:Preferences|系统设置]]确认了电子邮件地址且未被禁止使用“电邮联系”功能时,才可以使用它。您当前的IP地址是$3,该封禁ID是#$5。请在您做出的任何查询中包含所有上述详情。",
+       "autoblockedtext": "您的IP地址因曾被一位被$1封禁的用户使用而被自动封禁。封禁原因:\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。请在您做出的任何查询中包含所有上述详情。",
+       "systemblockedtext": "您的用户名或IP地址已被MediaWiki自动封禁。封禁原因:\n\n:<em>$2</em>\n\n* 开始时间:$8\n* 到期时间:$6\n* 目标用户:$7\n\n您当前的IP地址是$3。请在您做出的任何查询中包含所有上述详情。",
        "blockednoreason": "未给出原因",
        "whitelistedittext": "请$1以编辑页面。",
        "confirmedittext": "您必须确认您的电子邮件地址才能编辑页面。请通过[[Special:Preferences|系统设置]]设置并确认您的电子邮件地址。",
        "change-blocklink": "更改封禁",
        "contribslink": "贡献",
        "emaillink": "发送电子邮件",
-       "autoblocker": "因为您与“[[User:$1|$1]]”共享一个IP地址而被自动封禁。\n$1被封禁的理由是“$2”",
+       "autoblocker": "因为您与“[[User:$1|$1]]”共享一个IP地址而被自动封禁。$1被封禁的理由是“$2”",
        "blocklogpage": "封禁日志",
        "blocklog-showlog": "该用户曾被封禁。下面提供封禁日志以供参考:",
        "blocklog-showsuppresslog": "该用户曾被封禁并隐藏。下面提供封锁日志以供参考:",
        "interlanguage-link-title-nonlang": "$1——$2",
        "common.css": "/* 这里放置的CSS将应用于所有皮肤 */",
        "print.css": "/* 这里放置的CSS将影响打印输出 */",
-       "noscript.css": "/* 这里放置的CSS将影响用JavaScript的用户 */",
+       "noscript.css": "/* 这里放置的CSS将影响用JavaScript的用户 */",
        "group-autoconfirmed.css": "/* 这里放置的CSS将只影响自动确认用户 */",
        "group-user.css": "/* 这里放置的CSS将只影响注册用户 */",
        "group-bot.css": "/* 这里放置的CSS将只影响机器人 */",
        "group-bureaucrat.css": "/* 这里放置的CSS将只影响行政员 */",
        "common.js": "/* 这里的任何JavaScript将为所有用户在每次页面载入时加载。 */",
        "group-autoconfirmed.js": "/* 这里的任何JavaScript将只为自动确认用户加载 */",
-       "group-user.js": "/* 放置于此的JavaScript将只为注册用户加载 */",
+       "group-user.js": "/* 这里的任何JavaScript将只为注册用户加载 */",
        "group-bot.js": "/* 这里的任何JavaScript将只为机器人加载 */",
        "group-sysop.js": "/* 这里的任何JavaScript将只为管理员加载 */",
        "group-bureaucrat.js": "/* 这里的任何JavaScript将只为行政员加载 */",
        "pageinfo-length": "页面长度(字节)",
        "pageinfo-article-id": "页面ID",
        "pageinfo-language": "页面内容语言",
+       "pageinfo-language-change": "更改",
        "pageinfo-content-model": "页面内容类型",
        "pageinfo-content-model-change": "更改",
        "pageinfo-robot-policy": "爬虫索引",
        "restrictionsfield-badip": "无效的IP地址或段:$1",
        "restrictionsfield-label": "允许的IP段:",
        "restrictionsfield-help": "每行一个IP地址或CIDR段。要启用所有,可使用<br><code>0.0.0.0/0</code><br><code>::/0</code>",
+       "revid": "修订版本$1",
        "pageid": "页面ID$1"
 }
index 36655df..2eebf7d 100644 (file)
        "views": "檢視",
        "toolbox": "工具",
        "tool-link-userrights": "更改{{GENDER:$1|使用者}}群組",
+       "tool-link-userrights-readonly": "檢視{{GENDER:$1|使用者}}群組",
        "tool-link-emailuser": "寄信給這位{{GENDER:$1|使用者}}",
        "userpage": "檢視使用者頁面",
        "projectpage": "檢視專案頁面",
        "ok": "確定",
        "retrievedfrom": "取自 \"$1\"",
        "youhavenewmessages": "您有 $1 ($2)。",
-       "youhavenewmessagesfromusers": "有來自{{PLURAL:$3|另一位使用者|$3 位使用者}}的 $1 ($2)。",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|您}}有來自{{PLURAL:$3|另一位使用者|$3 位使用者}}的 $1 ($2)。",
        "youhavenewmessagesmanyusers": "你有來自多位使用者的 $1 ($2)。",
        "newmessageslinkplural": "{{PLURAL:$1|一則新訊息|999=新訊息}}",
        "newmessagesdifflinkplural": "最近{{PLURAL:$1|變更}}",
        "editusergroup": "加載用戶組",
        "editinguser": "變更{{GENDER:$1|使用者}} <strong>[[User:$1|$1]]</strong> 的使用者權限 $2",
        "userrights-editusergroup": "編輯使用者群組",
+       "userrights-viewusergroup": "檢視使用者群組",
        "saveusergroups": "儲存{{GENDER:$1|使用者}}群組",
        "userrights-groupsmember": "所屬群組:",
        "userrights-groupsmember-auto": "所屬隱含群組:",
        "listgrouprights-addgroup-all": "加入所有群組",
        "listgrouprights-removegroup-all": "移除所有群組",
        "listgrouprights-addgroup-self": "在自己的帳號中加入的{{PLURAL:$2|一個|多個}}群組: $1",
-       "listgrouprights-removegroup-self": "在自己的帳號中移除的{{PLURAL:$2|一個|多個}}群組: $1",
+       "listgrouprights-removegroup-self": "移除自己帳號中的{{PLURAL:$2|一個|多個}}群組: $1",
        "listgrouprights-addgroup-self-all": "在自己的帳號中加入所有群組",
-       "listgrouprights-removegroup-self-all": "在自己的帳號中移除所有群組",
+       "listgrouprights-removegroup-self-all": "移除自己帳號中的所有群組",
        "listgrouprights-namespaceprotection-header": "命名空間限制",
        "listgrouprights-namespaceprotection-namespace": "命名空間",
        "listgrouprights-namespaceprotection-restrictedto": "允許使用者編輯的權限",
        "log-action-filter-newusers-create": "由匿名使用者建立",
        "log-action-filter-newusers-create2": "由註冊使用者建立",
        "log-action-filter-newusers-autocreate": "自動建立",
-       "log-action-filter-newusers-byemail": "使用電子郵件送密碼建立",
+       "log-action-filter-newusers-byemail": "使用電子郵件送密碼建立",
        "log-action-filter-patrol-patrol": "手動巡查",
        "log-action-filter-patrol-autopatrol": "自動巡查",
        "log-action-filter-protect-protect": "保護",
index 7dde2b7..4edce3d 100644 (file)
@@ -174,10 +174,10 @@ $specialPageAliases = [
 
 $magicWords = [
        'redirect'                => [ 0, '#পুনর্নির্দেশ', '#পুনঃর্নির্দেশ', '#পুনঃনির্দেশ', '#পুননির্দেশ', '#REDIRECT' ],
-       'notoc'                   => [ 0, '__à¦\95à§\8bন_বিষà§\9fবসà§\8dতà§\81র_à¦\9bà¦\95_নà§\9f__', '__à¦\95à§\8bনবিষà§\9fবসà§\8dতà§\81রà¦\9bà¦\95নà§\9f__', '__à¦\95à§\8bন_বিষà§\9fবসà§\8dতà§\81র_à¦\9fà§\87বিল_নà§\9f__', '__à¦\95à§\8bনবিষà§\9fবসà§\8dতà§\81রà¦\9fà§\87বিলনà§\9f__', '__NOTOC__' ],
-       'nogallery'               => [ 0, '__à¦\95à§\8bনà¦\97à§\8dযালারিনà§\9f__', '__à¦\95à§\8bনà¦\97à§\8dযালারà§\80নà§\9f__', '__à¦\95à§\8bন_à¦\97à§\8dযালারি_নà§\9f__', '__à¦\95à§\8bন_à¦\97à§\8dযালারà§\80_নà§\9f__', '__NOGALLERY__' ],
-       'toc'                     => [ 0, '__বিষà§\9fবসà§\8dতà§\81র_à¦\9bà¦\95__', '__বিষà§\9fবসà§\8dতà§\81রà¦\9bà¦\95__', '__বিষà§\9fবসà§\8dতà§\81র_à¦\9fà§\87বিল__', '__বিষà§\9fবস্তুরটেবিল__', '__TOC__' ],
-       'noeditsection'           => [ 0, '__à¦\95à§\8bনসমà§\8dপাদনাà¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দনà§\9f__', '__à¦\95à§\8bন_সমà§\8dপাদনা_à¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দ_নà§\9f__', '__NOEDITSECTION__' ],
+       'notoc'                   => [ 0, '__à¦\95à§\8bন_বিষয়বসà§\8dতà§\81র_à¦\9bà¦\95_নয়__', '__à¦\95à§\8bনবিষয়বসà§\8dতà§\81রà¦\9bà¦\95নয়__', '__à¦\95à§\8bন_বিষয়বসà§\8dতà§\81র_à¦\9fà§\87বিল_নয়__', '__à¦\95à§\8bনবিষয়বসà§\8dতà§\81রà¦\9fà§\87বিলনয়__', '__NOTOC__' ],
+       'nogallery'               => [ 0, '__à¦\95à§\8bনà¦\97à§\8dযালারিনয়__', '__à¦\95à§\8bনà¦\97à§\8dযালারà§\80নয়__', '__à¦\95à§\8bন_à¦\97à§\8dযালারি_নয়__', '__à¦\95à§\8bন_à¦\97à§\8dযালারà§\80_নয়__', '__NOGALLERY__' ],
+       'toc'                     => [ 0, '__বিষয়বসà§\8dতà§\81র_à¦\9bà¦\95__', '__বিষয়বসà§\8dতà§\81রà¦\9bà¦\95__', '__বিষয়বসà§\8dতà§\81র_à¦\9fà§\87বিল__', '__বিষয়বস্তুরটেবিল__', '__TOC__' ],
+       'noeditsection'           => [ 0, '__à¦\95à§\8bনসমà§\8dপাদনাà¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দনয়__', '__à¦\95à§\8bন_সমà§\8dপাদনা_à¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দ_নয়__', '__NOEDITSECTION__' ],
        'currentmonth'            => [ 1, 'চলতি_মাস', 'চলতিমাস', 'বর্তমান_মাস', 'বর্তমানমাস', 'বর্তমান_মাস_২', 'বর্তমানমাস২', 'CURRENTMONTH', 'CURRENTMONTH2' ],
        'currentmonth1'           => [ 1, 'চলতি_মাস_১', 'চলতিমাস১', 'বর্তমান_মাস_১', 'বর্তমানমাস১', 'CURRENTMONTH1' ],
        'currentmonthname'        => [ 1, 'বর্তমান_মাসের_নাম', 'বর্তমানমাসেরনাম', 'CURRENTMONTHNAME' ],
@@ -187,24 +187,24 @@ $magicWords = [
        'currentday2'             => [ 1, 'বর্তমান_দিন_২', 'বর্তমানদিন২', 'আজকের_দিন_২', 'আজকেরদিন২', 'CURRENTDAY2' ],
        'currentdayname'          => [ 1, 'বর্তমান_দিনের_নাম', 'বর্তমানদিনেরনাম', 'আজকের_দিনের_নাম', 'আজকেরদিনেরনাম', 'CURRENTDAYNAME' ],
        'currentyear'             => [ 1, 'চলতি_বছর', 'চলতিবছর', 'বর্তমান_বছর', 'বর্তমানবছর', 'CURRENTYEAR' ],
-       'currenttime'             => [ 1, 'বরà§\8dতমান_সমà§\9f', 'বরà§\8dতমানসমà§\9f', 'à¦\8fà¦\96নà¦\95ার_সমà§\9f', 'à¦\8fà¦\96নà¦\95ারসমà§\9f', 'à¦\8fà¦\96ন_সমà§\9f', 'CURRENTTIME' ],
+       'currenttime'             => [ 1, 'বরà§\8dতমান_সময়', 'বরà§\8dতমানসময়', 'à¦\8fà¦\96নà¦\95ার_সময়', 'à¦\8fà¦\96নà¦\95ারসময়', 'à¦\8fà¦\96ন_সময়', 'CURRENTTIME' ],
        'currenthour'             => [ 1, 'বর্তমান_ঘণ্টা', 'বর্তমানঘণ্টা', 'বর্তমান_ঘন্টা', 'বর্তমানঘন্টা', 'এখনকার_ঘণ্টা', 'এখনকারঘণ্টা', 'CURRENTHOUR' ],
-       'localmonth'              => [ 1, 'সà§\8dথানà§\80à§\9f_মাস', 'সà§\8dথানà§\80à§\9fমাস', 'সà§\8dথানà§\80à§\9f_মাস_২', 'সà§\8dথানà§\80à§\9fমাস২', 'LOCALMONTH', 'LOCALMONTH2' ],
-       'localmonth1'             => [ 1, 'সà§\8dথানà§\80à§\9f_মাস_১', 'সà§\8dথানà§\80à§\9fমাস১', 'LOCALMONTH1' ],
-       'localmonthname'          => [ 1, 'সà§\8dথানà§\80à§\9f_মাসà§\87র_নাম', 'সà§\8dথানà§\80à§\9fমাসেরনাম', 'LOCALMONTHNAME' ],
-       'localmonthnamegen'       => [ 1, 'সà§\8dথানà§\80à§\9f_মাসà§\87র_নাম_à¦\89à§\8eপনà§\8dন', 'সà§\8dথানà§\80à§\9fমাসেরনামউৎপন্ন', 'LOCALMONTHNAMEGEN' ],
-       'localmonthabbrev'        => [ 1, 'সà§\8dথানà§\80à§\9f_মাস_সà¦\82à¦\95à§\8dষà§\87প', 'সà§\8dথানà§\80à§\9fমাসসà¦\82à¦\95à§\8dষà§\87প', 'সà§\8dথানà§\80à§\9f_মাস_সà¦\82à¦\95à§\8dষিপà§\8dত', 'সà§\8dথানà§\80à§\9fমাসসংক্ষিপ্ত', 'সংক্ষেপিত_স্থানীয়_মাস', 'সংক্ষেপিতস্থানীয়মাস', 'LOCALMONTHABBREV' ],
-       'localday'                => [ 1, 'সà§\8dথানà§\80à§\9f_দিন', 'সà§\8dথানà§\80à§\9fদিন', 'স্থানীয়_বার', 'স্থানীয়বার', 'LOCALDAY' ],
-       'localday2'               => [ 1, 'সà§\8dথানà§\80à§\9f_দিন_২', 'সà§\8dথানà§\80à§\9fদিন২', 'LOCALDAY2' ],
-       'localdayname'            => [ 1, 'সà§\8dথানà§\80à§\9f_দিনà§\87র_নাম', 'সà§\8dথানà§\80à§\9fদিনেরনাম', 'LOCALDAYNAME' ],
-       'localyear'               => [ 1, 'সà§\8dথানà§\80à§\9f_বà¦\9bর', 'সà§\8dথানà§\80à§\9fবছর', 'LOCALYEAR' ],
-       'localtime'               => [ 1, 'সà§\8dথানà§\80à§\9f_সমà§\9f', 'সà§\8dথানà§\80à§\9fসমà§\9f', 'LOCALTIME' ],
-       'localhour'               => [ 1, 'সà§\8dথানà§\80à§\9f_à¦\98ণà§\8dà¦\9fা', 'সà§\8dথানà§\80à§\9fà¦\98ণà§\8dà¦\9fা', 'সà§\8dথানà§\80à§\9f_à¦\98নà§\8dà¦\9fা', 'সà§\8dথানà§\80à§\9fঘন্টা', 'LOCALHOUR' ],
+       'localmonth'              => [ 1, 'সà§\8dথানà§\80য়_মাস', 'সà§\8dথানà§\80য়মাস', 'সà§\8dথানà§\80য়_মাস_২', 'সà§\8dথানà§\80য়মাস২', 'LOCALMONTH', 'LOCALMONTH2' ],
+       'localmonth1'             => [ 1, 'সà§\8dথানà§\80য়_মাস_১', 'সà§\8dথানà§\80য়মাস১', 'LOCALMONTH1' ],
+       'localmonthname'          => [ 1, 'সà§\8dথানà§\80য়_মাসà§\87র_নাম', 'সà§\8dথানà§\80য়মাসেরনাম', 'LOCALMONTHNAME' ],
+       'localmonthnamegen'       => [ 1, 'সà§\8dথানà§\80য়_মাসà§\87র_নাম_à¦\89à§\8eপনà§\8dন', 'সà§\8dথানà§\80য়মাসেরনামউৎপন্ন', 'LOCALMONTHNAMEGEN' ],
+       'localmonthabbrev'        => [ 1, 'সà§\8dথানà§\80য়_মাস_সà¦\82à¦\95à§\8dষà§\87প', 'সà§\8dথানà§\80য়মাসসà¦\82à¦\95à§\8dষà§\87প', 'সà§\8dথানà§\80য়_মাস_সà¦\82à¦\95à§\8dষিপà§\8dত', 'সà§\8dথানà§\80য়মাসসংক্ষিপ্ত', 'সংক্ষেপিত_স্থানীয়_মাস', 'সংক্ষেপিতস্থানীয়মাস', 'LOCALMONTHABBREV' ],
+       'localday'                => [ 1, 'সà§\8dথানà§\80য়_দিন', 'সà§\8dথানà§\80য়দিন', 'স্থানীয়_বার', 'স্থানীয়বার', 'LOCALDAY' ],
+       'localday2'               => [ 1, 'সà§\8dথানà§\80য়_দিন_২', 'সà§\8dথানà§\80য়দিন২', 'LOCALDAY2' ],
+       'localdayname'            => [ 1, 'সà§\8dথানà§\80য়_দিনà§\87র_নাম', 'সà§\8dথানà§\80য়দিনেরনাম', 'LOCALDAYNAME' ],
+       'localyear'               => [ 1, 'সà§\8dথানà§\80য়_বà¦\9bর', 'সà§\8dথানà§\80য়বছর', 'LOCALYEAR' ],
+       'localtime'               => [ 1, 'সà§\8dথানà§\80য়_সময়', 'সà§\8dথানà§\80য়সময়', 'LOCALTIME' ],
+       'localhour'               => [ 1, 'সà§\8dথানà§\80য়_à¦\98ণà§\8dà¦\9fা', 'সà§\8dথানà§\80য়à¦\98ণà§\8dà¦\9fা', 'সà§\8dথানà§\80য়_à¦\98নà§\8dà¦\9fা', 'সà§\8dথানà§\80য়ঘন্টা', 'LOCALHOUR' ],
        'numberofpages'           => [ 1, 'পাতার_সংখ্যা', 'পাতারসংখ্যা', 'পৃষ্ঠার_সংখ্যা', 'পৃষ্ঠারসংখ্যা', 'পৃষ্ঠা_সংখ্যা', 'পৃষ্ঠাসংখ্যা', 'NUMBEROFPAGES' ],
        'numberofarticles'        => [ 1, 'নিবন্ধের_সংখ্যা', 'নিবন্ধেরসংখ্যা', 'নিবন্ধ_সংখ্যা', 'নিবন্ধসংখ্যা', 'NUMBEROFARTICLES' ],
        'numberoffiles'           => [ 1, 'ফাইলের_সংখ্যা', 'ফাইলেরসংখ্যা', 'ফাইল_সংখ্যা', 'ফাইলসংখ্যা', 'NUMBEROFFILES' ],
        'numberofusers'           => [ 1, 'ব্যবহারকারীর_সংখ্যা', 'ব্যবহারকারীরসংখ্যা', 'ব্যবহারকারী_সংখ্যা', 'ব্যবহারকারীসংখ্যা', 'NUMBEROFUSERS' ],
-       'numberofactiveusers'     => [ 1, 'সà¦\95à§\8dরিà§\9f_বà§\8dযবহারà¦\95ারà§\80র_সà¦\82à¦\96à§\8dযা', 'সà¦\95à§\8dরিà§\9fবà§\8dযবহারà¦\95ারà§\80রসà¦\82à¦\96à§\8dযা', 'সà¦\95à§\8dরিà§\9f_বà§\8dযবহারà¦\95ারà§\80_সà¦\82à¦\96à§\8dযা', 'সà¦\95à§\8dরিà§\9fব্যবহারকারীসংখ্যা', 'NUMBEROFACTIVEUSERS' ],
+       'numberofactiveusers'     => [ 1, 'সà¦\95à§\8dরিয়_বà§\8dযবহারà¦\95ারà§\80র_সà¦\82à¦\96à§\8dযা', 'সà¦\95à§\8dরিয়বà§\8dযবহারà¦\95ারà§\80রসà¦\82à¦\96à§\8dযা', 'সà¦\95à§\8dরিয়_বà§\8dযবহারà¦\95ারà§\80_সà¦\82à¦\96à§\8dযা', 'সà¦\95à§\8dরিয়ব্যবহারকারীসংখ্যা', 'NUMBEROFACTIVEUSERS' ],
        'numberofedits'           => [ 1, 'সম্পাদনার_সংখ্যা', 'সম্পাদনারসংখ্যা', 'সম্পাদনা_সংখ্যা', 'সম্পাদনাসংখ্যা', 'NUMBEROFEDITS' ],
        'pagename'                => [ 1, 'পাতার_নাম', 'পাতারনাম', 'পৃষ্ঠার_নাম', 'পৃষ্ঠারনাম', 'PAGENAME' ],
        'pagenamee'               => [ 1, 'পাতার_নামম', 'পাতারনামম', 'পৃষ্ঠার_নামম', 'পৃষ্ঠারনামম', 'PAGENAMEE' ],
@@ -213,8 +213,8 @@ $magicWords = [
        'namespacenumber'         => [ 1, 'নামস্থানের_সংখ্যা', 'নামস্থানেরসংখ্যা', 'NAMESPACENUMBER' ],
        'talkspace'               => [ 1, 'আলাপের_স্থান', 'আলোচনার_স্থান', 'আলাপেরস্থান', 'আলোচনারস্থান', 'আলাপের_জায়গা', 'আলাপেরজায়গা', 'TALKSPACE' ],
        'talkspacee'              => [ 1, 'আলাপের_স্থানন', 'আলোচনার_স্থানন', 'আলাপেরস্থানন', 'আলোচনারস্থানন', 'TALKSPACEE' ],
-       'subjectspace'            => [ 1, 'বিষà§\9fà§\87র_সà§\8dথান', 'নিবনà§\8dধà§\87র_সà§\8dথান', 'বিষà§\9fেরস্থান', 'নিবন্ধেরস্থান', 'SUBJECTSPACE', 'ARTICLESPACE' ],
-       'subjectspacee'           => [ 1, 'বিষà§\9fà§\87র_সà§\8dথানন', 'নিবনà§\8dধà§\87র_সà§\8dথানন', 'বিষà§\9fেরস্থানন', 'নিবন্ধেরস্থানন', 'SUBJECTSPACEE', 'ARTICLESPACEE' ],
+       'subjectspace'            => [ 1, 'বিষয়à§\87র_সà§\8dথান', 'নিবনà§\8dধà§\87র_সà§\8dথান', 'বিষয়েরস্থান', 'নিবন্ধেরস্থান', 'SUBJECTSPACE', 'ARTICLESPACE' ],
+       'subjectspacee'           => [ 1, 'বিষয়à§\87র_সà§\8dথানন', 'নিবনà§\8dধà§\87র_সà§\8dথানন', 'বিষয়েরস্থানন', 'নিবন্ধেরস্থানন', 'SUBJECTSPACEE', 'ARTICLESPACEE' ],
        'fullpagename'            => [ 1, 'পূর্ণ_পাতার_নাম', 'সম্পূর্ণ_পাতার_নাম', 'পূর্ণপাতারনাম', 'সম্পূর্ণপাতারনাম', 'পূর্ণ_পৃষ্ঠার_নাম', 'সম্পূর্ণ_পৃষ্ঠার_নাম', 'পূর্ণপৃষ্ঠারনাম', 'সম্পূর্ণপৃষ্ঠারনাম', 'FULLPAGENAME' ],
        'fullpagenamee'           => [ 1, 'পূর্ণ_পাতার_নামম', 'সম্পূর্ণ_পাতার_নামম', 'পূর্ণপাতারনামম', 'সম্পূর্ণপাতারনামম', 'পূর্ণ_পৃষ্ঠার_নামম', 'সম্পূর্ণ_পৃষ্ঠার_নামম', 'পূর্ণপৃষ্ঠারনামম', 'সম্পূর্ণপৃষ্ঠারনামম', 'FULLPAGENAMEE' ],
        'subpagename'             => [ 1, 'উপপাতার_নাম', 'উপপাতারনাম', 'উপপৃষ্ঠার_নাম', 'উপপৃষ্ঠারনাম', 'SUBPAGENAME' ],
@@ -225,8 +225,8 @@ $magicWords = [
        'basepagenamee'           => [ 1, 'ভিত্তি_পাতার_নামম', 'ভিত্তিপাতারনামম', 'ভিত্তি_পৃষ্ঠার_নামম', 'ভিত্তি_পৃষ্ঠার_নামম', 'BASEPAGENAMEE' ],
        'talkpagename'            => [ 1, 'আলাপ_পাতার_নাম', 'আলাপপাতারনাম', 'আলাপ_পৃষ্ঠার_নাম', 'আলোচনা_পৃষ্ঠার_নাম', 'আলোচনা_পাতার_নাম', 'আলোচনাপাতারনাম', 'আলোচনা_পৃষ্ঠার_নাম', 'আলোচনা_পৃষ্ঠার_নাম', 'TALKPAGENAME' ],
        'talkpagenamee'           => [ 1, 'আলাপ_পাতার_নামম', 'আলাপপাতারনামম', 'আলাপ_পৃষ্ঠার_নামম', 'আলোচনা_পৃষ্ঠার_নামম', 'আলোচনা_পাতার_নামম', 'আলোচনাপাতারনামম', 'আলোচনা_পৃষ্ঠার_নামম', 'আলোচনা_পৃষ্ঠার_নামম', 'TALKPAGENAMEE' ],
-       'subjectpagename'         => [ 1, 'বিষà§\9fà§\87র_পাতার_নাম', 'বিষà§\9fà§\87রপাতারনাম', 'বিষà§\9fà§\87র_পà§\83ষà§\8dঠার_নাম', 'বিষà§\9fেরপৃষ্ঠারনাম', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
-       'subjectpagenamee'        => [ 1, 'বিষà§\9fà§\87র_পাতার_নামম', 'বিষà§\9fà§\87রপাতারনামম', 'বিষà§\9fà§\87র_পà§\83ষà§\8dঠার_নামম', 'বিষà§\9fেরপৃষ্ঠারনামম', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
+       'subjectpagename'         => [ 1, 'বিষয়à§\87র_পাতার_নাম', 'বিষয়à§\87রপাতারনাম', 'বিষয়à§\87র_পà§\83ষà§\8dঠার_নাম', 'বিষয়েরপৃষ্ঠারনাম', 'SUBJECTPAGENAME', 'ARTICLEPAGENAME' ],
+       'subjectpagenamee'        => [ 1, 'বিষয়à§\87র_পাতার_নামম', 'বিষয়à§\87রপাতারনামম', 'বিষয়à§\87র_পà§\83ষà§\8dঠার_নামম', 'বিষয়েরপৃষ্ঠারনামম', 'SUBJECTPAGENAMEE', 'ARTICLEPAGENAMEE' ],
        'img_thumbnail'           => [ 1, 'থাম্ব','থাম্বনেইল', 'thumb', 'thumbnail' ],
        'img_manualthumb'         => [ 1, 'থাম্ব=$1','থাম্বনেইল=$1', 'thumbnail=$1', 'thumb=$1' ],
        'img_right'               => [ 1, 'ডান', 'ডানে', 'right' ],
@@ -248,7 +248,7 @@ $magicWords = [
        'img_link'                => [ 1, 'সংযোগ=$1', 'লিঙ্ক=$1', 'link=$1' ],
        'img_class'               => [ 1, 'ক্লাস=$1', 'class=$1' ],
        'sitename'                => [ 1, 'সাইটের_নাম', 'সাইটেরনাম', 'SITENAME' ],
-       'localurl'                => [ 0, 'সà§\8dথানà§\80à§\9f_à¦\87à¦\89à¦\86রà¦\8fল:', 'সà§\8dথানà§\80à§\9fইউআরএল:', 'LOCALURL:' ],
+       'localurl'                => [ 0, 'সà§\8dথানà§\80য়_à¦\87à¦\89à¦\86রà¦\8fল:', 'সà§\8dথানà§\80য়ইউআরএল:', 'LOCALURL:' ],
        'articlepath'             => [ 0, 'নিবন্ধের_পথ', 'নিবন্ধেরপথ', 'ARTICLEPATH' ],
        'pageid'                  => [ 0, 'পাতার_আইডি', 'পাতারআইডি', 'পৃষ্ঠার_আইডি', 'পৃষ্ঠারআইডি', 'PAGEID' ],
        'server'                  => [ 0, 'সার্ভার', 'SERVER' ],
@@ -258,31 +258,31 @@ $magicWords = [
        'grammar'                 => [ 0, 'ব্যাকরণ:', 'GRAMMAR:' ],
        'gender'                  => [ 0, 'লিঙ্গ:', 'GENDER:' ],
        'bidi'                    => [ 0, 'বিআইডিআই:', 'BIDI:' ],
-       'notitleconvert'          => [ 0, '__à¦\95à§\8bন_শিরà§\8bনাম_রà§\82পানà§\8dতরà¦\95ারà§\80_নà§\9f__', '__à¦\95à§\8bনশিরà§\8bনামরà§\82পানà§\8dতরà¦\95ারà§\80নà§\9f__', '__NOTITLECONVERT__', '__NOTC__' ],
-       'nocontentconvert'        => [ 0, '__à¦\95à§\8bন_বিষà§\9fবসà§\8dতà§\81_রà§\82পানà§\8dতরà¦\95ারà§\80_নà§\9f__', '__à¦\95à§\8bনবিষà§\9fবসà§\8dতà§\81রà§\82পানà§\8dতরà¦\95ারà§\80নà§\9f__', '__NOCONTENTCONVERT__', '__NOCC__' ],
+       'notitleconvert'          => [ 0, '__à¦\95à§\8bন_শিরà§\8bনাম_রà§\82পানà§\8dতরà¦\95ারà§\80_নয়__', '__à¦\95à§\8bনশিরà§\8bনামরà§\82পানà§\8dতরà¦\95ারà§\80নয়__', '__NOTITLECONVERT__', '__NOTC__' ],
+       'nocontentconvert'        => [ 0, '__à¦\95à§\8bন_বিষয়বসà§\8dতà§\81_রà§\82পানà§\8dতরà¦\95ারà§\80_নয়__', '__à¦\95à§\8bনবিষয়বসà§\8dতà§\81রà§\82পানà§\8dতরà¦\95ারà§\80নয়__', '__NOCONTENTCONVERT__', '__NOCC__' ],
        'currentweek'             => [ 1, 'বর্তমান_সপ্তাহ', 'বর্তমানসপ্তাহ', 'চলতি_সপ্তাহ', 'চলতিসপ্তাহ', 'CURRENTWEEK' ],
        'currentdow'              => [ 1, 'বর্তমান_সপ্তাহের_দিন', 'বর্তমানসপ্তাহেরদিন', 'CURRENTDOW' ],
-       'localweek'               => [ 1, 'সà§\8dথানà§\80à§\9f_সপà§\8dতাহ', 'সà§\8dথানà§\80à§\9fসপ্তাহ', 'LOCALWEEK' ],
-       'localdow'                => [ 1, 'সà§\8dথানà§\80à§\9f_সপà§\8dতাহà§\87র_দিন', 'সà§\8dথানà§\80à§\9fসপ্তাহেরদিন', 'LOCALDOW' ],
+       'localweek'               => [ 1, 'সà§\8dথানà§\80য়_সপà§\8dতাহ', 'সà§\8dথানà§\80য়সপ্তাহ', 'LOCALWEEK' ],
+       'localdow'                => [ 1, 'সà§\8dথানà§\80য়_সপà§\8dতাহà§\87র_দিন', 'সà§\8dথানà§\80য়সপ্তাহেরদিন', 'LOCALDOW' ],
        'revisionid'              => [ 1, 'সংশোধনের_আইডি', 'সংশোধনেরআইডি', 'REVISIONID' ],
        'revisionday'             => [ 1, 'সংশোধনের_দিন', 'সংশোধনেরদিন', 'REVISIONDAY' ],
        'revisionday2'            => [ 1, 'সংশোধনের_দিন_২', 'সংশোধনেরদিন২', 'REVISIONDAY2' ],
        'revisionmonth'           => [ 1, 'সংশোধনের_মাস', 'সংশোধনেরমাস', 'REVISIONMONTH' ],
        'revisionmonth1'          => [ 1, 'সংশোধনের_মাস_১', 'সংশোধনেরমাস১', 'REVISIONMONTH1' ],
        'revisionyear'            => [ 1, 'সংশোধনের_বছর', 'সংশোধনেরবছর', 'REVISIONYEAR' ],
-       'revisiontimestamp'       => [ 1, 'সà¦\82শà§\8bধনà§\87র_সমà§\9fতারিà¦\96', 'সà¦\82শà§\8bধনà§\87রসমà§\9fতারিখ', 'REVISIONTIMESTAMP' ],
+       'revisiontimestamp'       => [ 1, 'সà¦\82শà§\8bধনà§\87র_সময়তারিà¦\96', 'সà¦\82শà§\8bধনà§\87রসময়তারিখ', 'REVISIONTIMESTAMP' ],
        'revisionuser'            => [ 1, 'সংশোধনের_ব্যবহারকারী', 'সংশোধনেরব্যবহারকারী', 'REVISIONUSER' ],
        'revisionsize'            => [ 1, 'সংশোধনের_আকার', 'সংশোধনেরআকার', 'REVISIONSIZE' ],
        'plural'                  => [ 0, 'বহুবচন:', 'PLURAL:' ],
        'raw'                     => [ 0, 'অবিন্যস্ত:', 'RAW:' ],
        'displaytitle'            => [ 1, 'প্রদর্শনের_শিরোনাম', 'প্রদর্শনেরশিরোনাম', 'প্রদর্শিত_শিরোনাম', 'প্রদর্শিতশিরোনাম', 'DISPLAYTITLE' ],
        'newsectionlink'          => [ 1, '__নতুন_অনুচ্ছেদের_সংযোগ__', '__নতুন_অনুচ্ছেদের_লিঙ্ক__', '__নতুনঅনুচ্ছেদেরসংযোগ__', '__নতুনঅনুচ্ছেদেরলিঙ্ক__', '__NEWSECTIONLINK__' ],
-       'nonewsectionlink'        => [ 1, '__à¦\95à§\8bন_নতà§\81ন_à¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দà§\87র_সà¦\82যà§\8bà¦\97_নà§\9f__', '__à¦\95à§\8bন_নতà§\81ন_à¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দà§\87র_লিà¦\99à§\8dà¦\95_নà§\9f__', '__à¦\95à§\8bননতà§\81নà¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দà§\87রসà¦\82যà§\8bà¦\97নà§\9f__', '__à¦\95à§\8bননতà§\81নà¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দà§\87রলিà¦\99à§\8dà¦\95নà§\9f__', '__NONEWSECTIONLINK__' ],
+       'nonewsectionlink'        => [ 1, '__à¦\95à§\8bন_নতà§\81ন_à¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দà§\87র_সà¦\82যà§\8bà¦\97_নয়__', '__à¦\95à§\8bন_নতà§\81ন_à¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দà§\87র_লিà¦\99à§\8dà¦\95_নয়__', '__à¦\95à§\8bননতà§\81নà¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দà§\87রসà¦\82যà§\8bà¦\97নয়__', '__à¦\95à§\8bননতà§\81নà¦\85নà§\81à¦\9aà§\8dà¦\9bà§\87দà§\87রলিà¦\99à§\8dà¦\95নয়__', '__NONEWSECTIONLINK__' ],
        'currentversion'          => [ 1, 'বর্তমান_সংস্করণ', 'বর্তমানসংস্করণ', 'CURRENTVERSION' ],
-       'currenttimestamp'        => [ 1, 'বরà§\8dতমান_সমà§\9fতারিà¦\96', 'বরà§\8dতমান_সমà§\9fতারিখ', 'CURRENTTIMESTAMP' ],
-       'localtimestamp'          => [ 1, 'সà§\8dথানà§\80à§\9f_সমà§\9fতারিà¦\96', 'সà§\8dথানà§\80à§\9fসমà§\9fতারিখ', 'LOCALTIMESTAMP' ],
+       'currenttimestamp'        => [ 1, 'বরà§\8dতমান_সময়তারিà¦\96', 'বরà§\8dতমান_সময়তারিখ', 'CURRENTTIMESTAMP' ],
+       'localtimestamp'          => [ 1, 'সà§\8dথানà§\80য়_সময়তারিà¦\96', 'সà§\8dথানà§\80য়সময়তারিখ', 'LOCALTIMESTAMP' ],
        'language'                => [ 0, '#ভাষা:', '#LANGUAGE:' ],
-       'contentlanguage'         => [ 1, 'বিষà§\9fবসà§\8dতà§\81র_ভাষা', 'বিষà§\9fবস্তুরভাষা', 'CONTENTLANGUAGE', 'CONTENTLANG' ],
+       'contentlanguage'         => [ 1, 'বিষয়বসà§\8dতà§\81র_ভাষা', 'বিষয়বস্তুরভাষা', 'CONTENTLANGUAGE', 'CONTENTLANG' ],
        'pagesinnamespace'        => [ 1, 'নামস্থানে_পাতা', 'নামস্থানে_পৃষ্ঠা', 'নামস্থানেপাতা', 'নামস্থানেপৃষ্ঠা', 'PAGESINNAMESPACE:', 'PAGESINNS:' ],
        'numberofadmins'          => [ 1, 'প্রশাসকের_সংখ্যা', 'প্রশাসকেরসংখ্যা', 'প্রশাসক_সংখ্যা', 'প্রশাসকসংখ্যা', 'NUMBEROFADMINS' ],
        'formatnum'               => [ 0, 'নম্বর_বিন্যাস', 'নম্বরবিন্যাস', 'FORMATNUM' ],
@@ -290,11 +290,11 @@ $magicWords = [
        'defaultsort'             => [ 1, 'পূর্বনির্ধারিত_বাছাই', 'পূর্বনির্ধারিতবাছাই', 'DEFAULTSORT:', 'DEFAULTSORTKEY:', 'DEFAULTCATEGORYSORT:' ],
        'filepath'                => [ 0, 'ফাইলের_পথ:', 'ফাইলেরপথ:', 'FILEPATH:' ],
        'tag'                     => [ 0, 'ট্যাগ', 'tag' ],
-       'hiddencat'               => [ 1, '__লà§\81à¦\95াà§\9fিতবিষà§\9fশ্রেণী__', '__লুক্কায়িতবিষয়শ্রেণী__', '__HIDDENCAT__' ],
-       'pagesincategory'         => [ 1, 'বিষà§\9fশà§\8dরà§\87ণà§\80তà§\87পাতা', 'বিষà§\9fশà§\8dরà§\87ণà§\80তà§\87পà§\83ষà§\8dঠা', 'বিষà§\9fশà§\8dরà§\87ণà§\80তà§\87_পাতা', 'বিষà§\9fশ্রেণীতে_পৃষ্ঠা', 'PAGESINCATEGORY', 'PAGESINCAT' ],
+       'hiddencat'               => [ 1, '__লà§\81à¦\95ায়িতবিষয়শ্রেণী__', '__লুক্কায়িতবিষয়শ্রেণী__', '__HIDDENCAT__' ],
+       'pagesincategory'         => [ 1, 'বিষয়শà§\8dরà§\87ণà§\80তà§\87পাতা', 'বিষয়শà§\8dরà§\87ণà§\80তà§\87পà§\83ষà§\8dঠা', 'বিষয়শà§\8dরà§\87ণà§\80তà§\87_পাতা', 'বিষয়শ্রেণীতে_পৃষ্ঠা', 'PAGESINCATEGORY', 'PAGESINCAT' ],
        'pagesize'                => [ 1, 'পাতার_আকার', 'পাতারআকার', 'পৃষ্ঠার_আকার', 'পৃষ্ঠারআকার', 'PAGESIZE' ],
        'index'                   => [ 1, '__নির্ঘণ্ট__', '__INDEX__' ],
-       'noindex'                 => [ 1, '__à¦\95à§\8bননিরà§\8dà¦\98ণà§\8dà¦\9fনà§\9f__', '__à¦\95à§\8bন_নিরà§\8dà¦\98ণà§\8dà¦\9f_নà§\9f__', '__নিরà§\8dà¦\98ণà§\8dà¦\9fনà§\9f__', '__NOINDEX__' ],
+       'noindex'                 => [ 1, '__à¦\95à§\8bননিরà§\8dà¦\98ণà§\8dà¦\9fনয়__', '__à¦\95à§\8bন_নিরà§\8dà¦\98ণà§\8dà¦\9f_নয়__', '__নিরà§\8dà¦\98ণà§\8dà¦\9fনয়__', '__NOINDEX__' ],
        'numberingroup'           => [ 1, 'দলে_সংখ্যা', 'দলেসংখ্যা', 'NUMBERINGROUP', 'NUMINGROUP' ],
        'staticredirect'          => [ 1, '__স্থির_পুনর্নির্দেশ__', '__স্থিরপুনর্নির্দেশ__', '__STATICREDIRECT__' ],
        'protectionlevel'         => [ 1, 'সুরক্ষার_স্তর', 'সুরক্ষারস্তর', 'সুরক্ষা_স্তর', 'সুরক্ষাস্তর', 'PROTECTIONLEVEL' ],
@@ -304,7 +304,7 @@ $magicWords = [
        'url_wiki'                => [ 0, 'উইকি', 'WIKI' ],
        'pagesincategory_all'     => [ 0, 'সব', 'সকল', 'all' ],
        'pagesincategory_pages'   => [ 0, 'পাতাসমূহ', 'পৃষ্ঠাসমূহ', 'pages' ],
-       'pagesincategory_subcats' => [ 0, 'à¦\89পবিষà§\9fশ্রেণী', '', 'subcats' ],
+       'pagesincategory_subcats' => [ 0, 'à¦\89পবিষয়শ্রেণী', '', 'subcats' ],
        'pagesincategory_files'   => [ 0, 'ফাইলসমূহ', 'files' ],
 ];
 
index c97ef25..32844a2 100644 (file)
@@ -109,3 +109,4 @@ $magicWords = [
        'pagesincategory_pages'     => [ '0', 'rûpel', 'pages' ],
 ];
 
+$linkTrail = '/^([a-zçêîşûẍḧÇÊÎŞÛẌḦ]+)(.*)$/sDu';
index 477f76a..ddbebbd 100644 (file)
 
 $fallback = 'zh-hans';
 
+$datePreferences = [
+       'default',
+       'wuu',
+       'ISO 8601',
+];
+
+$defaultDateFormat = 'wuu';
+
+$dateFormats = [
+       'wuu time' => 'H:i',
+       'wuu date' => 'Y年n月j号 (D)',
+       'wuu both' => 'Y年n月j号 (D) H:i',
+];
diff --git a/maintenance/archives/patch-externallinks-el_index_60.sql b/maintenance/archives/patch-externallinks-el_index_60.sql
new file mode 100644 (file)
index 0000000..eacb107
--- /dev/null
@@ -0,0 +1,4 @@
+-- @since 1.29
+ALTER TABLE /*$wgDBprefix*/externallinks ADD COLUMN el_index_60 varbinary(60) NOT NULL DEFAULT '';
+CREATE INDEX /*i*/el_index_60 ON /*_*/externallinks (el_index_60, el_id);
+CREATE INDEX /*i*/el_from_index_60 ON /*_*/externallinks (el_from, el_index_60, el_id);
index 18c7f11..befafc1 100644 (file)
@@ -163,7 +163,7 @@ class BackupDumper extends Maintenance {
                                        $val = explode( ':', $param );
 
                                        if ( count( $val ) === 1 ) {
-                                               $this->loadPlugin( $val[0] );
+                                               $this->loadPlugin( $val[0], '' );
                                        } elseif ( count( $val ) === 2 ) {
                                                $this->loadPlugin( $val[0], $val[1] );
                                        } else {
diff --git a/maintenance/importImages.inc b/maintenance/importImages.inc
deleted file mode 100644 (file)
index fc9428d..0000000
+++ /dev/null
@@ -1,137 +0,0 @@
-<?php
-/**
- * Support functions for the importImages.php script
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup Maintenance
- * @author Rob Church <robchur@gmail.com>
- * @author Mij <mij@bitchx.it>
- */
-
-/**
- * Search a directory for files with one of a set of extensions
- *
- * @param string $dir Path to directory to search
- * @param array $exts Array of extensions to search for
- * @param bool $recurse Search subdirectories recursively
- * @return array|bool Array of filenames on success, or false on failure
- */
-function findFiles( $dir, $exts, $recurse = false ) {
-       if ( is_dir( $dir ) ) {
-               $dhl = opendir( $dir );
-               if ( $dhl ) {
-                       $files = [];
-                       while ( ( $file = readdir( $dhl ) ) !== false ) {
-                               if ( is_file( $dir . '/' . $file ) ) {
-                                       list( /* $name */, $ext ) = splitFilename( $dir . '/' . $file );
-                                       if ( array_search( strtolower( $ext ), $exts ) !== false ) {
-                                               $files[] = $dir . '/' . $file;
-                                       }
-                               } elseif ( $recurse && is_dir( $dir . '/' . $file ) && $file !== '..' && $file !== '.' ) {
-                                       $files = array_merge( $files, findFiles( $dir . '/' . $file, $exts, true ) );
-                               }
-                       }
-
-                       return $files;
-               } else {
-                       return [];
-               }
-       } else {
-               return [];
-       }
-}
-
-/**
- * Split a filename into filename and extension
- *
- * @param string $filename Filename
- * @return array
- */
-function splitFilename( $filename ) {
-       $parts = explode( '.', $filename );
-       $ext = $parts[count( $parts ) - 1];
-       unset( $parts[count( $parts ) - 1] );
-       $fname = implode( '.', $parts );
-
-       return [ $fname, $ext ];
-}
-
-/**
- * Find an auxilliary file with the given extension, matching
- * the give base file path. $maxStrip determines how many extensions
- * may be stripped from the original file name before appending the
- * new extension. For example, with $maxStrip = 1 (the default),
- * file files acme.foo.bar.txt and acme.foo.txt would be auxilliary
- * files for acme.foo.bar and the extension ".txt". With $maxStrip = 2,
- * acme.txt would also be acceptable.
- *
- * @param string $file Base path
- * @param string $auxExtension The extension to be appended to the base path
- * @param int $maxStrip The maximum number of extensions to strip from the base path (default: 1)
- * @return string|bool
- */
-function findAuxFile( $file, $auxExtension, $maxStrip = 1 ) {
-       if ( strpos( $auxExtension, '.' ) !== 0 ) {
-               $auxExtension = '.' . $auxExtension;
-       }
-
-       $d = dirname( $file );
-       $n = basename( $file );
-
-       while ( $maxStrip >= 0 ) {
-               $f = $d . '/' . $n . $auxExtension;
-
-               if ( file_exists( $f ) ) {
-                       return $f;
-               }
-
-               $idx = strrpos( $n, '.' );
-               if ( !$idx ) {
-                       break;
-               }
-
-               $n = substr( $n, 0, $idx );
-               $maxStrip -= 1;
-       }
-
-       return false;
-}
-
-# @todo FIXME: Access the api in a saner way and performing just one query
-# (preferably batching files too).
-function getFileCommentFromSourceWiki( $wiki_host, $file ) {
-       $url = $wiki_host . '/api.php?action=query&format=xml&titles=File:'
-               . rawurlencode( $file ) . '&prop=imageinfo&&iiprop=comment';
-       $body = Http::get( $url, [], __METHOD__ );
-       if ( preg_match( '#<ii comment="([^"]*)" />#', $body, $matches ) == 0 ) {
-               return false;
-       }
-
-       return html_entity_decode( $matches[1] );
-}
-
-function getFileUserFromSourceWiki( $wiki_host, $file ) {
-       $url = $wiki_host . '/api.php?action=query&format=xml&titles=File:'
-               . rawurlencode( $file ) . '&prop=imageinfo&&iiprop=user';
-       $body = Http::get( $url, [], __METHOD__ );
-       if ( preg_match( '#<ii user="([^"]*)" />#', $body, $matches ) == 0 ) {
-               return false;
-       }
-
-       return html_entity_decode( $matches[1] );
-}
index 5a4ab39..7f2a9e1 100644 (file)
  * @author Mij <mij@bitchx.it>
  */
 
-$optionsWithArgs = [
-       'extensions', 'comment', 'comment-file', 'comment-ext', 'summary', 'user',
-       'license', 'sleep', 'limit', 'from', 'source-wiki-url', 'timestamp',
-];
+require_once __DIR__ . '/Maintenance.php';
+
+class ImportImages extends Maintenance {
+
+       public function __construct() {
+               parent::__construct();
+
+               $this->addDescription( 'Imports images and other media files into the wiki' );
+               $this->addArg( 'dir', 'Path to the directory containing images to be imported' );
+
+               $this->addOption( 'extensions',
+                       'Comma-separated list of allowable extensions, defaults to $wgFileExtensions',
+                       false,
+                       true
+               );
+               $this->addOption( 'overwrite',
+                       'Overwrite existing images with the same name (default is to skip them)' );
+               $this->addOption( 'limit',
+                       'Limit the number of images to process. Ignored or skipped images are not counted',
+                       false,
+                       true
+               );
+               $this->addOption( 'from',
+                       "Ignore all files until the one with the given name. Useful for resuming aborted "
+                               . "imports. The name should be the file's canonical database form.",
+                       false,
+                       true
+               );
+               $this->addOption( 'skip-dupes',
+                       'Skip images that were already uploaded under a different name (check SHA1)' );
+               $this->addOption( 'search-recursively', 'Search recursively for files in subdirectories' );
+               $this->addOption( 'sleep',
+                       'Sleep between files. Useful mostly for debugging',
+                       false,
+                       true
+               );
+               $this->addOption( 'user',
+                       "Set username of uploader, default 'Maintenance script'",
+                       false,
+                       true
+               );
+               // This parameter can optionally have an argument. If none specified, getOption()
+               // returns 1 which is precisely what we need.
+               $this->addOption( 'check-userblock', 'Check if the user got blocked during import' );
+               $this->addOption( 'comment',
+                       "Set file description, default 'Importing file'",
+                       false,
+                       true
+               );
+               $this->addOption( 'comment-file',
+                       'Set description to the content of this file',
+                       false,
+                       true
+               );
+               $this->addOption( 'comment-ext',
+                       'Causes the description for each file to be loaded from a file with the same name, but '
+                               . 'the extension provided. If a global description is also given, it is appended.',
+                       false,
+                       true
+               );
+               $this->addOption( 'summary',
+                       'Upload summary, description will be used if not provided',
+                       false,
+                       true
+               );
+               $this->addOption( 'license',
+                       'Use an optional license template',
+                       false,
+                       true
+               );
+               $this->addOption( 'timestamp',
+                       'Override upload time/date, all MediaWiki timestamp formats are accepted',
+                       false,
+                       true
+               );
+               $this->addOption( 'protect',
+                       'Specify the protect value (autoconfirmed,sysop)',
+                       false,
+                       true
+               );
+               $this->addOption( 'unprotect', 'Unprotects all uploaded images' );
+               $this->addOption( 'source-wiki-url',
+                       'If specified, take User and Comment data for each imported file from this URL. '
+                               . 'For example, --source-wiki-url="http://en.wikipedia.org/',
+                       false,
+                       true
+               );
+               $this->addOption( 'dry', "Dry run, don't import anything" );
+       }
 
-$optionsWithoutArgs = [
-       'protect', 'unprotect', 'search-recursively', 'check-userblock', 'overwrite',
-       'skip-dupes', 'dry'
-];
+       public function execute() {
+               global $wgFileExtensions, $wgUser, $wgRestrictionLevels;
 
-require_once __DIR__ . '/commandLine.inc';
-require_once __DIR__ . '/importImages.inc';
-$processed = $added = $ignored = $skipped = $overwritten = $failed = 0;
+               $processed = $added = $ignored = $skipped = $overwritten = $failed = 0;
 
-echo "Import Images\n\n";
+               $this->output( "Import Images\n\n" );
 
-# Need a path
-if ( count( $args ) == 0 ) {
-       showUsage();
-}
+               $dir = $this->getArg( 0 );
 
-$dir = $args[0];
+               # Check Protection
+               if ( $this->hasOption( 'protect' ) && $this->hasOption( 'unprotect' ) ) {
+                       $this->error( "Cannot specify both protect and unprotect.  Only 1 is allowed.\n", 1 );
+               }
 
-# Check Protection
-if ( isset( $options['protect'] ) && isset( $options['unprotect'] ) ) {
-       die( "Cannot specify both protect and unprotect.  Only 1 is allowed.\n" );
-}
+               if ( $this->hasOption( 'protect' ) && trim( $this->getOption( 'protect' ) ) ) {
+                       $this->error( "You must specify a protection option.\n", 1 );
+               }
 
-if ( isset( $options['protect'] ) && $options['protect'] == 1 ) {
-       die( "You must specify a protection option.\n" );
-}
+               # Prepare the list of allowed extensions
+               $extensions = $this->hasOption( 'extensions' )
+                       ? explode( ',', strtolower( $this->getOption( 'extensions' ) ) )
+                       : $wgFileExtensions;
 
-# Prepare the list of allowed extensions
-global $wgFileExtensions;
-$extensions = isset( $options['extensions'] )
-       ? explode( ',', strtolower( $options['extensions'] ) )
-       : $wgFileExtensions;
-
-# Search the path provided for candidates for import
-$files = findFiles( $dir, $extensions, isset( $options['search-recursively'] ) );
-
-# Initialise the user for this operation
-$user = isset( $options['user'] )
-       ? User::newFromName( $options['user'] )
-       : User::newSystemUser( 'Maintenance script', [ 'steal' => true ] );
-if ( !$user instanceof User ) {
-       $user = User::newSystemUser( 'Maintenance script', [ 'steal' => true ] );
-}
-$wgUser = $user;
-
-# Get block check. If a value is given, this specified how often the check is performed
-if ( isset( $options['check-userblock'] ) ) {
-       if ( !$options['check-userblock'] ) {
-               $checkUserBlock = 1;
-       } else {
-               $checkUserBlock = (int)$options['check-userblock'];
-       }
-} else {
-       $checkUserBlock = false;
-}
+               # Search the path provided for candidates for import
+               $files = $this->findFiles( $dir, $extensions, $this->hasOption( 'search-recursively' ) );
 
-# Get --from
-MediaWiki\suppressWarnings();
-$from = $options['from'];
-MediaWiki\restoreWarnings();
+               # Initialise the user for this operation
+               $user = $this->hasOption( 'user' )
+                       ? User::newFromName( $this->getOption( 'user' ) )
+                       : User::newSystemUser( 'Maintenance script', [ 'steal' => true ] );
+               if ( !$user instanceof User ) {
+                       $user = User::newSystemUser( 'Maintenance script', [ 'steal' => true ] );
+               }
+               $wgUser = $user;
+
+               # Get block check. If a value is given, this specified how often the check is performed
+               $checkUserBlock = (int)$this->getOption( 'check-userblock' );
+
+               $from = $this->getOption( 'from' );
+               $sleep = (int)$this->getOption( 'sleep' );
+               $limit = (int)$this->getOption( 'limit' );
+               $timestamp = $this->getOption( 'timestamp', false );
+
+               # Get the upload comment. Provide a default one in case there's no comment given.
+               $commentFile = $this->getOption( 'comment-file' );
+               if ( $commentFile !== null ) {
+                       $comment = file_get_contents( $commentFile );
+                       if ( $comment === false || $comment === null ) {
+                               $this->error( "failed to read comment file: {$commentFile}\n", 1 );
+                       }
+               } else {
+                       $comment = $this->getOption( 'comment', 'Importing file' );
+               }
+               $commentExt = $this->getOption( 'comment-ext' );
+               $summary = $this->getOption( 'summary', '' );
 
-# Get sleep time.
-MediaWiki\suppressWarnings();
-$sleep = $options['sleep'];
-MediaWiki\restoreWarnings();
+               $license = $this->getOption( 'license', '' );
 
-if ( $sleep ) {
-       $sleep = (int)$sleep;
-}
+               $sourceWikiUrl = $this->getOption( 'source-wiki-url' );
 
-# Get limit number
-MediaWiki\suppressWarnings();
-$limit = $options['limit'];
-MediaWiki\restoreWarnings();
+               # Batch "upload" operation
+               $count = count( $files );
+               if ( $count > 0 ) {
 
-if ( $limit ) {
-       $limit = (int)$limit;
-}
+                       foreach ( $files as $file ) {
+                               $base = UtfNormal\Validator::cleanUp( wfBaseName( $file ) );
 
-$timestamp = isset( $options['timestamp'] ) ? $options['timestamp'] : false;
+                               # Validate a title
+                               $title = Title::makeTitleSafe( NS_FILE, $base );
+                               if ( !is_object( $title ) ) {
+                                       $this->output(
+                                               "{$base} could not be imported; a valid title cannot be produced\n" );
+                                       continue;
+                               }
 
-# Get the upload comment. Provide a default one in case there's no comment given.
-$comment = 'Importing file';
+                               if ( $from ) {
+                                       if ( $from == $title->getDBkey() ) {
+                                               $from = null;
+                                       } else {
+                                               $ignored++;
+                                               continue;
+                                       }
+                               }
 
-if ( isset( $options['comment-file'] ) ) {
-       $comment = file_get_contents( $options['comment-file'] );
-       if ( $comment === false || $comment === null ) {
-               die( "failed to read comment file: {$options['comment-file']}\n" );
-       }
-} elseif ( isset( $options['comment'] ) ) {
-       $comment = $options['comment'];
-}
+                               if ( $checkUserBlock && ( ( $processed % $checkUserBlock ) == 0 ) ) {
+                                       $user->clearInstanceCache( 'name' ); // reload from DB!
+                                       if ( $user->isBlocked() ) {
+                                               $this->output( $user->getName() . " was blocked! Aborting.\n" );
+                                               break;
+                                       }
+                               }
 
-$commentExt = isset( $options['comment-ext'] ) ? $options['comment-ext'] : false;
+                               # Check existence
+                               $image = wfLocalFile( $title );
+                               if ( $image->exists() ) {
+                                       if ( $this->hasOption( 'overwrite' ) ) {
+                                               $this->output( "{$base} exists, overwriting..." );
+                                               $svar = 'overwritten';
+                                       } else {
+                                               $this->output( "{$base} exists, skipping\n" );
+                                               $skipped++;
+                                               continue;
+                                       }
+                               } else {
+                                       if ( $this->hasOption( 'skip-dupes' ) ) {
+                                               $repo = $image->getRepo();
+                                               # XXX: we end up calculating this again when actually uploading. that sucks.
+                                               $sha1 = FSFile::getSha1Base36FromPath( $file );
+
+                                               $dupes = $repo->findBySha1( $sha1 );
+
+                                               if ( $dupes ) {
+                                                       $this->output(
+                                                               "{$base} already exists as {$dupes[0]->getName()}, skipping\n" );
+                                                       $skipped++;
+                                                       continue;
+                                               }
+                                       }
 
-$summary = isset( $options['summary'] ) ? $options['summary'] : '';
+                                       $this->output( "Importing {$base}..." );
+                                       $svar = 'added';
+                               }
 
-# Get the license specifier
-$license = isset( $options['license'] ) ? $options['license'] : '';
+                               if ( $sourceWikiUrl ) {
+                                       /* find comment text directly from source wiki, through MW's API */
+                                       $real_comment = $this->getFileCommentFromSourceWiki( $sourceWikiUrl, $base );
+                                       if ( $real_comment === false ) {
+                                               $commentText = $comment;
+                                       } else {
+                                               $commentText = $real_comment;
+                                       }
 
-# Batch "upload" operation
-$count = count( $files );
-if ( $count > 0 ) {
+                                       /* find user directly from source wiki, through MW's API */
+                                       $real_user = $this->getFileUserFromSourceWiki( $sourceWikiUrl, $base );
+                                       if ( $real_user === false ) {
+                                               $wgUser = $user;
+                                       } else {
+                                               $wgUser = User::newFromName( $real_user );
+                                               if ( $wgUser === false ) {
+                                                       # user does not exist in target wiki
+                                                       $this->output(
+                                                               "failed: user '$real_user' does not exist in target wiki." );
+                                                       continue;
+                                               }
+                                       }
+                               } else {
+                                       # Find comment text
+                                       $commentText = false;
+
+                                       if ( $commentExt ) {
+                                               $f = $this->findAuxFile( $file, $commentExt );
+                                               if ( !$f ) {
+                                                       $this->output( " No comment file with extension {$commentExt} found "
+                                                                . "for {$file}, using default comment. " );
+                                               } else {
+                                                       $commentText = file_get_contents( $f );
+                                                       if ( !$commentText ) {
+                                                               $this->output(
+                                                                       " Failed to load comment file {$f}, using default comment. " );
+                                                       }
+                                               }
+                                       }
 
-       foreach ( $files as $file ) {
-               $base = UtfNormal\Validator::cleanUp( wfBaseName( $file ) );
+                                       if ( !$commentText ) {
+                                               $commentText = $comment;
+                                       }
+                               }
 
-               # Validate a title
-               $title = Title::makeTitleSafe( NS_FILE, $base );
-               if ( !is_object( $title ) ) {
-                       echo "{$base} could not be imported; a valid title cannot be produced\n";
-                       continue;
-               }
+                               # Import the file
+                               if ( $this->hasOption( 'dry' ) ) {
+                                       $this->output(
+                                               " publishing {$file} by '{$wgUser->getName()}', comment '$commentText'... "
+                                       );
+                               } else {
+                                       $mwProps = new MWFileProps( MimeMagic::singleton() );
+                                       $props = $mwProps->getPropsFromPath( $file, true );
+                                       $flags = 0;
+                                       $publishOptions = [];
+                                       $handler = MediaHandler::getHandler( $props['mime'] );
+                                       if ( $handler ) {
+                                               $publishOptions['headers'] = $handler->getStreamHeaders( $props['metadata'] );
+                                       } else {
+                                               $publishOptions['headers'] = [];
+                                       }
+                                       $archive = $image->publish( $file, $flags, $publishOptions );
+                                       if ( !$archive->isGood() ) {
+                                               $this->output( "failed. (" .
+                                                        $archive->getWikiText( false, false, 'en' ) .
+                                                        ")\n" );
+                                               $failed++;
+                                               continue;
+                                       }
+                               }
 
-               if ( $from ) {
-                       if ( $from == $title->getDBkey() ) {
-                               $from = null;
-                       } else {
-                               $ignored++;
-                               continue;
-                       }
-               }
+                               $commentText = SpecialUpload::getInitialPageText( $commentText, $license );
+                               if ( !$this->hasOption( 'summary' ) ) {
+                                       $summary = $commentText;
+                               }
 
-               if ( $checkUserBlock && ( ( $processed % $checkUserBlock ) == 0 ) ) {
-                       $user->clearInstanceCache( 'name' ); // reload from DB!
-                       if ( $user->isBlocked() ) {
-                               echo $user->getName() . " was blocked! Aborting.\n";
-                               break;
-                       }
-               }
+                               if ( $this->hasOption( 'dry' ) ) {
+                                       $this->output( "done.\n" );
+                               } elseif ( $image->recordUpload2(
+                                       $archive->value,
+                                       $summary,
+                                       $commentText,
+                                       $props,
+                                       $timestamp
+                               ) ) {
+                                       # We're done!
+                                       $this->output( "done.\n" );
 
-               # Check existence
-               $image = wfLocalFile( $title );
-               if ( $image->exists() ) {
-                       if ( isset( $options['overwrite'] ) ) {
-                               echo "{$base} exists, overwriting...";
-                               $svar = 'overwritten';
-                       } else {
-                               echo "{$base} exists, skipping\n";
-                               $skipped++;
-                               continue;
-                       }
-               } else {
-                       if ( isset( $options['skip-dupes'] ) ) {
-                               $repo = $image->getRepo();
-                               # XXX: we end up calculating this again when actually uploading. that sucks.
-                               $sha1 = FSFile::getSha1Base36FromPath( $file );
+                                       $doProtect = false;
 
-                               $dupes = $repo->findBySha1( $sha1 );
+                                       $protectLevel = $this->getOption( 'protect' );
 
-                               if ( $dupes ) {
-                                       echo "{$base} already exists as " . $dupes[0]->getName() . ", skipping\n";
-                                       $skipped++;
-                                       continue;
+                                       if ( $protectLevel && in_array( $protectLevel, $wgRestrictionLevels ) ) {
+                                               $doProtect = true;
+                                       }
+                                       if ( $this->hasOption( 'unprotect' ) ) {
+                                               $protectLevel = '';
+                                               $doProtect = true;
+                                       }
+
+                                       if ( $doProtect ) {
+                                               # Protect the file
+                                               $this->output( "\nWaiting for replica DBs...\n" );
+                                               // Wait for replica DBs.
+                                               sleep( 2.0 ); # Why this sleep?
+                                               wfWaitForSlaves();
+
+                                               $this->output( "\nSetting image restrictions ... " );
+
+                                               $cascade = false;
+                                               $restrictions = [];
+                                               foreach ( $title->getRestrictionTypes() as $type ) {
+                                                       $restrictions[$type] = $protectLevel;
+                                               }
+
+                                               $page = WikiPage::factory( $title );
+                                               $status = $page->doUpdateRestrictions( $restrictions, [], $cascade, '', $user );
+                                               $this->output( ( $status->isOK() ? 'done' : 'failed' ) . "\n" );
+                                       }
+                               } else {
+                                       $this->output( "failed. (at recordUpload stage)\n" );
+                                       $svar = 'failed';
                                }
-                       }
 
-                       echo "Importing {$base}...";
-                       $svar = 'added';
-               }
+                               $$svar++;
+                               $processed++;
 
-               if ( isset( $options['source-wiki-url'] ) ) {
-                       /* find comment text directly from source wiki, through MW's API */
-                       $real_comment = getFileCommentFromSourceWiki( $options['source-wiki-url'], $base );
-                       if ( $real_comment === false ) {
-                               $commentText = $comment;
-                       } else {
-                               $commentText = $real_comment;
+                               if ( $limit && $processed >= $limit ) {
+                                       break;
+                               }
+
+                               if ( $sleep ) {
+                                       sleep( $sleep );
+                               }
                        }
 
-                       /* find user directly from source wiki, through MW's API */
-                       $real_user = getFileUserFromSourceWiki( $options['source-wiki-url'], $base );
-                       if ( $real_user === false ) {
-                               $wgUser = $user;
-                       } else {
-                               $wgUser = User::newFromName( $real_user );
-                               if ( $wgUser === false ) {
-                                       # user does not exist in target wiki
-                                       echo "failed: user '$real_user' does not exist in target wiki.";
-                                       continue;
+                       # Print out some statistics
+                       $this->output( "\n" );
+                       foreach (
+                               [
+                                       'count' => 'Found',
+                                       'limit' => 'Limit',
+                                       'ignored' => 'Ignored',
+                                       'added' => 'Added',
+                                       'skipped' => 'Skipped',
+                                       'overwritten' => 'Overwritten',
+                                       'failed' => 'Failed'
+                               ] as $var => $desc
+                       ) {
+                               if ( $$var > 0 ) {
+                                       $this->output( "{$desc}: {$$var}\n" );
                                }
                        }
                } else {
-                       # Find comment text
-                       $commentText = false;
-
-                       if ( $commentExt ) {
-                               $f = findAuxFile( $file, $commentExt );
-                               if ( !$f ) {
-                                       echo " No comment file with extension {$commentExt} found "
-                                               . "for {$file}, using default comment. ";
-                               } else {
-                                       $commentText = file_get_contents( $f );
-                                       if ( !$commentText ) {
-                                               echo " Failed to load comment file {$f}, using default comment. ";
+                       $this->output( "No suitable files could be found for import.\n" );
+               }
+       }
+
+       /**
+        * Search a directory for files with one of a set of extensions
+        *
+        * @param string $dir Path to directory to search
+        * @param array $exts Array of extensions to search for
+        * @param bool $recurse Search subdirectories recursively
+        * @return array|bool Array of filenames on success, or false on failure
+        */
+       private function findFiles( $dir, $exts, $recurse = false ) {
+               if ( is_dir( $dir ) ) {
+                       $dhl = opendir( $dir );
+                       if ( $dhl ) {
+                               $files = [];
+                               while ( ( $file = readdir( $dhl ) ) !== false ) {
+                                       if ( is_file( $dir . '/' . $file ) ) {
+                                               list( /* $name */, $ext ) = $this->splitFilename( $dir . '/' . $file );
+                                               if ( array_search( strtolower( $ext ), $exts ) !== false ) {
+                                                       $files[] = $dir . '/' . $file;
+                                               }
+                                       } elseif ( $recurse && is_dir( $dir . '/' . $file ) && $file !== '..' && $file !== '.' ) {
+                                               $files = array_merge( $files, $this->findFiles( $dir . '/' . $file, $exts, true ) );
                                        }
                                }
-                       }
-
-                       if ( !$commentText ) {
-                               $commentText = $comment;
-                       }
-               }
 
-               # Import the file
-               if ( isset( $options['dry'] ) ) {
-                       echo " publishing {$file} by '" . $wgUser->getName() . "', comment '$commentText'... ";
-               } else {
-                       $mwProps = new MWFileProps( MimeMagic::singleton() );
-                       $props = $mwProps->getPropsFromPath( $file, true );
-                       $flags = 0;
-                       $publishOptions = [];
-                       $handler = MediaHandler::getHandler( $props['mime'] );
-                       if ( $handler ) {
-                               $publishOptions['headers'] = $handler->getStreamHeaders( $props['metadata'] );
+                               return $files;
                        } else {
-                               $publishOptions['headers'] = [];
+                               return [];
                        }
-                       $archive = $image->publish( $file, $flags, $publishOptions );
-                       if ( !$archive->isGood() ) {
-                               echo "failed. (" .
-                                       $archive->getWikiText( false, false, 'en' ) .
-                                       ")\n";
-                               $failed++;
-                               continue;
-                       }
-               }
-
-               $commentText = SpecialUpload::getInitialPageText( $commentText, $license );
-               if ( !isset( $options['summary'] ) ) {
-                       $summary = $commentText;
+               } else {
+                       return [];
                }
+       }
 
-               if ( isset( $options['dry'] ) ) {
-                       echo "done.\n";
-               } elseif ( $image->recordUpload2(
-                       $archive->value,
-                       $summary,
-                       $commentText,
-                       $props,
-                       $timestamp
-               ) ) {
-                       # We're done!
-                       echo "done.\n";
+       /**
+        * Split a filename into filename and extension
+        *
+        * @param string $filename Filename
+        * @return array
+        */
+       private function splitFilename( $filename ) {
+               $parts = explode( '.', $filename );
+               $ext = $parts[count( $parts ) - 1];
+               unset( $parts[count( $parts ) - 1] );
+               $fname = implode( '.', $parts );
+
+               return [ $fname, $ext ];
+       }
 
-                       $doProtect = false;
+       /**
+        * Find an auxilliary file with the given extension, matching
+        * the give base file path. $maxStrip determines how many extensions
+        * may be stripped from the original file name before appending the
+        * new extension. For example, with $maxStrip = 1 (the default),
+        * file files acme.foo.bar.txt and acme.foo.txt would be auxilliary
+        * files for acme.foo.bar and the extension ".txt". With $maxStrip = 2,
+        * acme.txt would also be acceptable.
+        *
+        * @param string $file Base path
+        * @param string $auxExtension The extension to be appended to the base path
+        * @param int $maxStrip The maximum number of extensions to strip from the base path (default: 1)
+        * @return string|bool
+        */
+       private function findAuxFile( $file, $auxExtension, $maxStrip = 1 ) {
+               if ( strpos( $auxExtension, '.' ) !== 0 ) {
+                       $auxExtension = '.' . $auxExtension;
+               }
 
-                       global $wgRestrictionLevels;
+               $d = dirname( $file );
+               $n = basename( $file );
 
-                       $protectLevel = isset( $options['protect'] ) ? $options['protect'] : null;
+               while ( $maxStrip >= 0 ) {
+                       $f = $d . '/' . $n . $auxExtension;
 
-                       if ( $protectLevel && in_array( $protectLevel, $wgRestrictionLevels ) ) {
-                               $doProtect = true;
-                       }
-                       if ( isset( $options['unprotect'] ) ) {
-                               $protectLevel = '';
-                               $doProtect = true;
+                       if ( file_exists( $f ) ) {
+                               return $f;
                        }
 
-                       if ( $doProtect ) {
-                               # Protect the file
-                               echo "\nWaiting for replica DBs...\n";
-                               // Wait for replica DBs.
-                               sleep( 2.0 ); # Why this sleep?
-                               wfWaitForSlaves();
-
-                               echo "\nSetting image restrictions ... ";
-
-                               $cascade = false;
-                               $restrictions = [];
-                               foreach ( $title->getRestrictionTypes() as $type ) {
-                                       $restrictions[$type] = $protectLevel;
-                               }
-
-                               $page = WikiPage::factory( $title );
-                               $status = $page->doUpdateRestrictions( $restrictions, [], $cascade, '', $user );
-                               echo ( $status->isOK() ? 'done' : 'failed' ) . "\n";
+                       $idx = strrpos( $n, '.' );
+                       if ( !$idx ) {
+                               break;
                        }
-               } else {
-                       echo "failed. (at recordUpload stage)\n";
-                       $svar = 'failed';
-               }
 
-               $$svar++;
-               $processed++;
-
-               if ( $limit && $processed >= $limit ) {
-                       break;
+                       $n = substr( $n, 0, $idx );
+                       $maxStrip -= 1;
                }
 
-               if ( $sleep ) {
-                       sleep( $sleep );
-               }
+               return false;
        }
 
-       # Print out some statistics
-       echo "\n";
-       foreach (
-               [
-                       'count' => 'Found',
-                       'limit' => 'Limit',
-                       'ignored' => 'Ignored',
-                       'added' => 'Added',
-                       'skipped' => 'Skipped',
-                       'overwritten' => 'Overwritten',
-                       'failed' => 'Failed'
-               ] as $var => $desc
-       ) {
-               if ( $$var > 0 ) {
-                       echo "{$desc}: {$$var}\n";
+       # @todo FIXME: Access the api in a saner way and performing just one query
+       # (preferably batching files too).
+       private function getFileCommentFromSourceWiki( $wiki_host, $file ) {
+               $url = $wiki_host . '/api.php?action=query&format=xml&titles=File:'
+                          . rawurlencode( $file ) . '&prop=imageinfo&&iiprop=comment';
+               $body = Http::get( $url, [], __METHOD__ );
+               if ( preg_match( '#<ii comment="([^"]*)" />#', $body, $matches ) == 0 ) {
+                       return false;
                }
+
+               return html_entity_decode( $matches[1] );
        }
-} else {
-       echo "No suitable files could be found for import.\n";
-}
 
-exit( 0 );
+       private function getFileUserFromSourceWiki( $wiki_host, $file ) {
+               $url = $wiki_host . '/api.php?action=query&format=xml&titles=File:'
+                          . rawurlencode( $file ) . '&prop=imageinfo&&iiprop=user';
+               $body = Http::get( $url, [], __METHOD__ );
+               if ( preg_match( '#<ii user="([^"]*)" />#', $body, $matches ) == 0 ) {
+                       return false;
+               }
 
-function showUsage( $reason = false ) {
-       if ( $reason ) {
-               echo $reason . "\n";
+               return html_entity_decode( $matches[1] );
        }
 
-       echo <<<TEXT
-Imports images and other media files into the wiki
-USAGE: php importImages.php [options] <dir>
-
-<dir> : Path to the directory containing images to be imported
-
-Options:
---extensions=<exts>     Comma-separated list of allowable extensions, defaults
-                        to \$wgFileExtensions.
---overwrite             Overwrite existing images with the same name (default
-                        is to skip them).
---limit=<num>           Limit the number of images to process. Ignored or
-                        skipped images are not counted.
---from=<name>           Ignore all files until the one with the given name.
-                        Useful for resuming aborted imports. <name> should be
-                        the file's canonical database form.
---skip-dupes            Skip images that were already uploaded under a different
-                        name (check SHA1).
---search-recursively    Search recursively for files in subdirectories.
---sleep=<sec>           Sleep between files. Useful mostly for debugging.
---user=<username>       Set username of uploader, default 'Maintenance script'.
---check-userblock       Check if the user got blocked during import.
---comment=<text>        Set file description, default 'Importing file'.
---comment-file=<file>   Set description to the content of <file>.
---comment-ext=<ext>     Causes the description for each file to be loaded from a
-                        file with the same name, but the extension <ext>. If a
-                        global description is also given, it is appended.
---license=<code>        Use an optional license template.
---dry                   Dry run, don't import anything.
---protect=<protect>     Specify the protect value (autoconfirmed,sysop).
---summary=<summary>     Upload summary, description will be used if not
-                        provided.
---timestamp=<timestamp> Override upload time/date, all MediaWiki timestamp
-                        formats are accepted.
---unprotect             Unprotects all uploaded images.
---source-wiki-url       If specified, take User and Comment data for each
-                        imported file from this URL. For example,
-                        --source-wiki-url="http://en.wikipedia.org/."
-
-TEXT;
-       exit( 1 );
 }
+
+$maintClass = 'ImportImages';
+require_once RUN_MAINTENANCE_IF_MAIN;
index 256ee36..ba1f752 100644 (file)
@@ -389,11 +389,18 @@ CREATE TABLE /*_*/externallinks (
   -- which allows for fast searching for all pages under example.com with the
   -- clause:
   --      WHERE el_index LIKE 'http://com.example.%'
-  el_index nvarchar(450) NOT NULL
+  el_index nvarchar(450) NOT NULL,
+
+  -- This is el_index truncated to 60 bytes to allow for sortable queries that
+  -- aren't supported by a partial index.
+  -- @todo Drop the default once this is deployed everywhere and code is populating it.
+  el_index_60 varbinary(60) NOT NULL default ''
 );
 
 CREATE INDEX /*i*/el_from ON /*_*/externallinks (el_from);
 CREATE INDEX /*i*/el_index ON /*_*/externallinks (el_index);
+CREATE INDEX /*i*/el_index_60 ON /*_*/externallinks (el_index_60, el_id);
+CREATE INDEX /*i*/el_from_index_60 ON /*_*/externallinks (el_from, el_index_60, el_id);
 -- el_to index intentionally not added; we cannot index nvarchar(max) columns,
 -- but we also cannot restrict el_to to a smaller column size as the external
 -- link may be larger.
diff --git a/maintenance/oracle/archives/patch-externallinks-el_index_60.sql b/maintenance/oracle/archives/patch-externallinks-el_index_60.sql
new file mode 100644 (file)
index 0000000..c4b906d
--- /dev/null
@@ -0,0 +1,5 @@
+define mw_prefix='{$wgDBprefix}';
+
+ALTER TABLE &mw_prefix.externallinks ADD el_index_60 VARBINARY(60) NOT NULL DEFAULT '';
+CREATE INDEX &mw_prefix.externallinks_i04 ON &mw_prefix.externallinks (el_index_60, el_id);
+CREATE INDEX &mw_prefix.externallinks_i05 ON &mw_prefix.externallinks (el_from, el_index_60, el_id);
index 616b401..edb3398 100644 (file)
@@ -219,13 +219,16 @@ CREATE TABLE &mw_prefix.externallinks (
   el_id     NUMBER  NOT NULL,
   el_from   NUMBER  NOT NULL,
   el_to     VARCHAR2(2048) NOT NULL,
-  el_index  VARCHAR2(2048) NOT NULL
+  el_index  VARCHAR2(2048) NOT NULL,
+  el_index_60  VARBINARY(60) NOT NULL DEFAULT ''
 );
 ALTER TABLE &mw_prefix.externallinks ADD CONSTRAINT &mw_prefix.externallinks_pk PRIMARY KEY (el_id);
 ALTER TABLE &mw_prefix.externallinks ADD CONSTRAINT &mw_prefix.externallinks_fk1 FOREIGN KEY (el_from) REFERENCES &mw_prefix.page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED;
 CREATE INDEX &mw_prefix.externallinks_i01 ON &mw_prefix.externallinks (el_from, el_to);
 CREATE INDEX &mw_prefix.externallinks_i02 ON &mw_prefix.externallinks (el_to, el_from);
 CREATE INDEX &mw_prefix.externallinks_i03 ON &mw_prefix.externallinks (el_index);
+CREATE INDEX &mw_prefix.externallinks_i04 ON &mw_prefix.externallinks (el_index_60, el_id);
+CREATE INDEX &mw_prefix.externallinks_i05 ON &mw_prefix.externallinks (el_from, el_index_60, el_id);
 
 CREATE TABLE &mw_prefix.langlinks (
   ll_from    NUMBER  NOT NULL,
index e4f3e91..2da8830 100644 (file)
@@ -57,7 +57,7 @@ class Orphans extends Maintenance {
        /**
         * Lock the appropriate tables for the script
         * @param Database $db
-        * @param string $extraTable The name of any extra tables to lock (eg: text)
+        * @param string[] $extraTable The name of any extra tables to lock (eg: text)
         */
        private function lockTables( $db, $extraTable = [] ) {
                $tbls = [ 'page', 'revision', 'redirect' ];
index 2273761..61ad075 100644 (file)
@@ -254,13 +254,16 @@ CREATE INDEX cl_sortkey     ON categorylinks (cl_to, cl_sortkey, cl_from);
 
 CREATE SEQUENCE externallinks_el_id_seq;
 CREATE TABLE externallinks (
-  el_id     INTEGER  NOT NULL  PRIMARY KEY DEFAULT nextval('externallinks_el_id_seq'),
-  el_from   INTEGER  NOT NULL  REFERENCES page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
-  el_to     TEXT     NOT NULL,
-  el_index  TEXT     NOT NULL
+  el_id       INTEGER     NOT NULL  PRIMARY KEY DEFAULT nextval('externallinks_el_id_seq'),
+  el_from     INTEGER     NOT NULL  REFERENCES page(page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
+  el_to       TEXT        NOT NULL,
+  el_index    TEXT        NOT NULL,
+  el_index_60 BYTEA       NOT NULL  DEFAULT ''
 );
 CREATE INDEX externallinks_from_to ON externallinks (el_from,el_to);
 CREATE INDEX externallinks_index   ON externallinks (el_index);
+CREATE INDEX el_index_60           ON externallinks (el_index_60, el_id);
+CREATE INDEX el_from_index_60      ON externallinks (el_from, el_index_60, el_id);
 
 CREATE TABLE langlinks (
   ll_from    INTEGER  NOT NULL  REFERENCES page (page_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
index cf60d89..2b6ea03 100644 (file)
@@ -676,12 +676,19 @@ CREATE TABLE /*_*/externallinks (
   -- which allows for fast searching for all pages under example.com with the
   -- clause:
   --      WHERE el_index LIKE 'http://com.example.%'
-  el_index blob NOT NULL
+  el_index blob NOT NULL,
+
+  -- This is el_index truncated to 60 bytes to allow for sortable queries that
+  -- aren't supported by a partial index.
+  -- @todo Drop the default once this is deployed everywhere and code is populating it.
+  el_index_60 varbinary(60) NOT NULL default ''
 ) /*$wgDBTableOptions*/;
 
 CREATE INDEX /*i*/el_from ON /*_*/externallinks (el_from, el_to(40));
 CREATE INDEX /*i*/el_to ON /*_*/externallinks (el_to(60), el_from);
 CREATE INDEX /*i*/el_index ON /*_*/externallinks (el_index(60));
+CREATE INDEX /*i*/el_index_60 ON /*_*/externallinks (el_index_60, el_id);
+CREATE INDEX /*i*/el_from_index_60 ON /*_*/externallinks (el_from, el_index_60, el_id);
 
 --
 -- Track interlanguage links
diff --git a/maintenance/view.php b/maintenance/view.php
new file mode 100644 (file)
index 0000000..af7eb2d
--- /dev/null
@@ -0,0 +1,59 @@
+<?php
+/**
+ * Show page contents.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup Maintenance
+ */
+
+require_once __DIR__ . '/Maintenance.php';
+
+/**
+ * Maintenance script to show page contents.
+ *
+ * @ingroup Maintenance
+ */
+class ViewCLI extends Maintenance {
+       public function __construct() {
+               parent::__construct();
+               $this->addDescription( 'Show article contents on the command line' );
+               $this->addArg( 'title', 'Title of article to view' );
+       }
+
+       public function execute() {
+               $title = Title::newFromText( $this->getArg() );
+               if ( !$title ) {
+                       $this->error( "Invalid title", true );
+               }
+
+               $page = WikiPage::factory( $title );
+
+               $content = $page->getContent( Revision::RAW );
+               if ( !$content ) {
+                       $this->error( "Page has no content", true );
+               }
+               if ( !$content instanceof TextContent ) {
+                       $this->error( "Non-text content models not supported", true );
+               }
+
+               $this->output( $content->getNativeData() );
+       }
+}
+
+$maintClass = "ViewCLI";
+require_once RUN_MAINTENANCE_IF_MAIN;
index 99e752c..e415d66 100644 (file)
@@ -6,6 +6,7 @@
     "postdoc": "grunt copy:jsduck"
   },
   "devDependencies": {
+    "eslint": "3.12.2",
     "eslint-config-wikimedia": "0.3.0",
     "grunt": "1.0.1",
     "grunt-banana-checker": "0.5.0",
index 4932a29..e8be528 100644 (file)
@@ -1174,7 +1174,6 @@ return [
                        'searchsuggest-containing',
                ],
                'dependencies' => [
-                       'jquery.client',
                        'jquery.placeholder',
                        'jquery.suggestions',
                        'jquery.getAttrs',
@@ -1592,15 +1591,12 @@ return [
                        'dsb' => 'resources/src/mediawiki.language/languages/dsb.js',
                        'fi' => 'resources/src/mediawiki.language/languages/fi.js',
                        'ga' => 'resources/src/mediawiki.language/languages/ga.js',
-                       'he' => 'resources/src/mediawiki.language/languages/he.js',
                        'hsb' => 'resources/src/mediawiki.language/languages/hsb.js',
                        'hu' => 'resources/src/mediawiki.language/languages/hu.js',
                        'hy' => 'resources/src/mediawiki.language/languages/hy.js',
                        'la' => 'resources/src/mediawiki.language/languages/la.js',
                        'os' => 'resources/src/mediawiki.language/languages/os.js',
-                       'ru' => 'resources/src/mediawiki.language/languages/ru.js',
                        'sl' => 'resources/src/mediawiki.language/languages/sl.js',
-                       'uk' => 'resources/src/mediawiki.language/languages/uk.js',
                ],
                'dependencies' => [
                        'mediawiki.language.data',
@@ -2033,11 +2029,9 @@ return [
        ],
        'mediawiki.special.watchlist' => [
                'scripts' => 'resources/src/mediawiki.special/mediawiki.special.watchlist.js',
-               'messages' => 'watchlist-mark-all-visited',
                'dependencies' => [
                        'mediawiki.api',
-                       'mediawiki.jqueryMsg',
-                       'oojs-ui-windows',
+                       'oojs-ui-core',
                        'user.options',
                ]
        ],
index 2c6a588..ddda432 100644 (file)
             }
         };
 
-        if (!options.live) this.each(function() { get(this); });
+        this.each(function() { get(this); });
 
         if ( options.trigger != 'manual' ) {
             var eventIn  = options.trigger == 'hover' ? 'mouseenter focus' : 'focus',
                 eventOut = options.trigger == 'hover' ? 'mouseleave blur' : 'blur';
             if ( options.live ) {
                 mw.track( 'mw.deprecate', 'tipsy-live' );
-                mw.log.warn( 'Use of the "live" option of jquery.tipsy is deprecated.' );
-                // XXX: The official status of 'context' is deprecated, and the official status of
-                // 'selector' is removed, so this really needs to go.
-                $( this.context )
-                    .on( eventIn, this.selector, enter )
-                    .on( eventOut, this.selector, leave );
-            } else {
-                this
-                    .on( eventIn, enter )
-                    .on( eventOut, leave );
+                mw.log.warn( 'Use of the "live" option of jquery.tipsy is no longer supported.' );
             }
+            this
+                .on( eventIn, enter )
+                .on( eventOut, leave );
         }
 
         return this;
diff --git a/resources/src/mediawiki.language/languages/he.js b/resources/src/mediawiki.language/languages/he.js
deleted file mode 100644 (file)
index 5bf8c4d..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*!
- * Hebrew (עברית) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'he', 'grammarForms' );
-       if ( grammarForms && grammarForms[ form ] ) {
-               return grammarForms[ form ][ word ];
-       }
-       switch ( form ) {
-               case 'prefixed':
-               case 'תחילית': // the same word in Hebrew
-                       // Duplicate prefixed "Waw", but only if it's not already double
-                       if ( word.slice( 0, 1 ) === 'ו' && word.slice( 0, 2 ) !== 'וו' ) {
-                               word = 'ו' + word;
-                       }
-
-                       // Remove the "He" if prefixed
-                       if ( word.slice( 0, 1 ) === 'ה' ) {
-                               word = word.slice( 1 );
-                       }
-
-                       // Add a hyphen (maqaf) before numbers and non-Hebrew letters
-                       if ( word.slice( 0, 1 ) < 'א' || word.slice( 0, 1 ) > 'ת' ) {
-                               word = '־' + word;
-                       }
-       }
-       return word;
-};
diff --git a/resources/src/mediawiki.language/languages/ru.js b/resources/src/mediawiki.language/languages/ru.js
deleted file mode 100644 (file)
index 09d7c0b..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*!
- * Russian (Русский) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       'use strict';
-
-       var forms, transformations, i, rule, sourcePattern, regexp, replacement;
-
-       forms = mediaWiki.language.getData( 'ru', 'grammarForms' );
-       if ( forms && forms[ form ] ) {
-               return forms[ form ][ word ];
-       }
-
-       transformations = mediaWiki.language.getData( 'ru', 'grammarTransformations' );
-
-       if ( !transformations[ form ] ) {
-               return word;
-       }
-
-       for ( i = 0; i < transformations[ form ].length; i++ ) {
-               rule = transformations[ form ][ i ];
-               sourcePattern = rule[ 0 ];
-
-               if ( sourcePattern === '@metadata' ) {
-                       continue;
-               }
-
-               regexp = new RegExp( sourcePattern );
-               replacement = rule[ 1 ];
-
-               if ( word.match( regexp ) ) {
-                       return word.replace( regexp, replacement );
-               }
-       }
-
-       return word;
-};
diff --git a/resources/src/mediawiki.language/languages/uk.js b/resources/src/mediawiki.language/languages/uk.js
deleted file mode 100644 (file)
index 138045c..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*!
- * Ukrainian (Українська) language functions
- */
-
-mediaWiki.language.convertGrammar = function ( word, form ) {
-       var grammarForms = mediaWiki.language.getData( 'uk', 'grammarForms' );
-       if ( grammarForms && grammarForms[ form ] ) {
-               return grammarForms[ form ][ word ];
-       }
-       switch ( form ) {
-               case 'genitive': // родовий відмінок
-                       if ( word.slice( -2 ) === 'ія' ) {
-                               word = word.slice( 0, -2 ) + 'ії';
-                       } else if ( word.slice( -2 ) === 'ти' ) {
-                               word = word.slice( 0, -2 ) + 'т';
-                       } else if ( word.slice( -2 ) === 'ди' ) {
-                               word = word.slice( 0, -2 ) + 'дів';
-                       } else if ( word.slice( -3 ) === 'ник' ) {
-                               word = word.slice( 0, -3 ) + 'ника';
-                       }
-
-                       break;
-               case 'accusative': // знахідний відмінок
-                       if ( word.slice( -2 ) === 'ія' ) {
-                               word = word.slice( 0, -2 ) + 'ію';
-                       }
-
-                       break;
-       }
-
-       return word;
-};
index fc2af3d..3726a68 100644 (file)
 
                /**
                 * Grammatical transformations, needed for inflected languages.
-                * Invoked by putting `{{grammar:form|word}}` in a message.
+                * Invoked by putting `{{grammar:case|word}}` in a message.
                 *
                 * The rules can be defined in $wgGrammarForms global or computed
                 * dynamically by overriding this method per language.
                 * @return {string}
                 */
                convertGrammar: function ( word, form ) {
-                       var grammarForms = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'grammarForms' );
-                       if ( grammarForms && grammarForms[ form ] ) {
-                               return grammarForms[ form ][ word ] || word;
+                       var userLanguage, forms, transformations,
+                               patterns, i, rule, sourcePattern, regexp, replacement;
+
+                       userLanguage = mw.config.get( 'wgUserLanguage' );
+
+                       forms = mw.language.getData( userLanguage, 'grammarForms' );
+                       if ( forms && forms[ form ] ) {
+                               return forms[ form ][ word ];
+                       }
+
+                       transformations = mediaWiki.language.getData( userLanguage, 'grammarTransformations' );
+
+                       if ( !( transformations && transformations[ form ] ) ) {
+                               return word;
+                       }
+
+                       patterns = transformations[ form ];
+
+                       // Some names of grammar rules are aliases for other rules.
+                       // In such cases the value is a string rather than object,
+                       // so load the actual rules.
+                       if ( typeof patterns === 'string' ) {
+                               patterns = transformations[ patterns ];
                        }
+
+                       for ( i = 0; i < patterns.length; i++ ) {
+                               rule = patterns[ i ];
+                               sourcePattern = rule[ 0 ];
+
+                               if ( sourcePattern === '@metadata' ) {
+                                       continue;
+                               }
+
+                               regexp = new RegExp( sourcePattern );
+                               replacement = rule[ 1 ];
+
+                               if ( word.match( regexp ) ) {
+                                       return word.replace( regexp, replacement );
+                               }
+                       }
+
                        return word;
                },
 
index 42392ed..81896de 100644 (file)
@@ -244,7 +244,7 @@ input#wpSummary {
 .catlinks li {
        display: inline-block;
        line-height: 1.25em;
-       border-left: 1px solid #aaa;
+       border-left: 1px solid #a2a9b1;
        margin: 0.125em 0;
        padding: 0 0.5em;
        zoom: 1;
@@ -363,7 +363,7 @@ table.wikitable > tr > th,
 table.wikitable > tr > td,
 table.wikitable > * > tr > th,
 table.wikitable > * > tr > td {
-       border: 1px solid #aaa;
+       border: 1px solid #a2a9b1;
        padding: 0.2em 0.4em;
 }
 
@@ -482,7 +482,7 @@ table.wikitable > caption {
 .mw-datatable,
 .mw-datatable td,
 .mw-datatable th {
-       border: 1px solid #aaa;
+       border: 1px solid #a2a9b1;
        padding: 0 0.15em 0 0.15em;
 }
 
@@ -495,7 +495,7 @@ table.wikitable > caption {
 }
 
 .mw-datatable tr:hover td {
-       background-color: #eef;
+       background-color: #eaf3ff;
 }
 
 /* Correct directionality when page dir is different from site/user dir */
index 33ceb48..83b78a8 100644 (file)
@@ -88,8 +88,8 @@ img {
 
 hr {
        height: 1px;
-       color: #aaa;
-       background-color: #aaa;
+       color: #a2a9b1;
+       background-color: #a2a9b1;
        border: 0;
        margin: .2em 0;
 }
@@ -108,7 +108,7 @@ h6 {
        overflow: hidden;
        padding-top: .5em;
        padding-bottom: .17em;
-       border-bottom: 1px solid #aaa;
+       border-bottom: 1px solid #a2a9b1;
 }
 
 h1 {
index 60155fd..43321fe 100644 (file)
                                                } else {
                                                        n = +value;
                                                        return !isNaN( n ) && isFinite( n ) &&
-                                                               // eslint-disable-next-line no-bitwise
-                                                               ( n | 0 ) === n &&
+                                                               Math.floor( n ) === n &&
                                                                n >= pi.min && n <= pi.apiSandboxMax;
                                                }
                                        } );
index bfe2c1c..7cc9b9b 100644 (file)
@@ -3,49 +3,48 @@
  */
 ( function ( mw, $, OO ) {
        $( function () {
-               var $resetForm = $( '#mw-watchlist-resetbutton' ),
-                       $progressBar = new OO.ui.ProgressBarWidget( { progress: false } ).$element;
-
-               $progressBar.css( {
-                       visibility: 'hidden',
-                       position: 'absolute',
-                       width: '100%'
-               } );
-               $resetForm.append( $progressBar );
+               var $progressBar, $resetForm = $( '#mw-watchlist-resetbutton' );
 
                // If the user wants to reset their watchlist, use an API call to do so (no reload required)
                // Adapted from a user script by User:NQ of English Wikipedia
                // (User:NQ/WatchlistResetConfirm.js)
                $resetForm.submit( function ( event ) {
-                       event.preventDefault();
+                       var $button = $resetForm.find( 'input[name=mw-watchlist-reset-submit]' );
 
-                       OO.ui.confirm( mw.msg( 'watchlist-mark-all-visited' ) ).done( function ( confirmed ) {
-                               var $button;
-
-                               if ( confirmed ) {
-                                       // Disable reset button to prevent multiple requests and show progress bar
-                                       $button = $resetForm.find( 'input[name=mw-watchlist-reset-submit]' ).prop( 'disabled', true );
-                                       $progressBar.css( 'visibility', 'visible' );
-
-                                       // Use action=setnotificationtimestamp to mark all as visited,
-                                       // then set all watchlist lines accordingly
-                                       new mw.Api().postWithToken( 'csrf', {
-                                               formatversion: 2,
-                                               action: 'setnotificationtimestamp',
-                                               entirewatchlist: true
-                                       } ).done( function () {
-                                               $button.css( 'visibility', 'hidden' );
-                                               $progressBar.css( 'visibility', 'hidden' );
-                                               $( '.mw-changeslist-line-watched' )
-                                                       .removeClass( 'mw-changeslist-line-watched' )
-                                                       .addClass( 'mw-changeslist-line-not-watched' );
-                                       } ).fail( function () {
-                                               // On error, fall back to server-side reset
-                                               // First remove this submit listener and then re-submit the form
-                                               $resetForm.off( 'submit' ).submit();
-                                       } );
+                       event.preventDefault();
 
-                               }
+                       // Disable reset button to prevent multiple concurrent requests
+                       $button.prop( 'disabled', true );
+
+                       if ( !$progressBar ) {
+                               $progressBar = new OO.ui.ProgressBarWidget( { progress: false } ).$element;
+                               $progressBar.css( {
+                                       position: 'absolute',
+                                       width: '100%'
+                               } );
+                       }
+                       // Show progress bar
+                       $resetForm.append( $progressBar );
+
+                       // Use action=setnotificationtimestamp to mark all as visited,
+                       // then set all watchlist lines accordingly
+                       new mw.Api().postWithToken( 'csrf', {
+                               formatversion: 2,
+                               action: 'setnotificationtimestamp',
+                               entirewatchlist: true
+                       } ).done( function () {
+                               // Enable button again
+                               $button.prop( 'disabled', false );
+                               // Hide the button because further clicks can not generate any visual changes
+                               $button.css( 'visibility', 'hidden' );
+                               $progressBar.detach();
+                               $( '.mw-changeslist-line-watched' )
+                                       .removeClass( 'mw-changeslist-line-watched' )
+                                       .addClass( 'mw-changeslist-line-not-watched' );
+                       } ).fail( function () {
+                               // On error, fall back to server-side reset
+                               // First remove this submit listener and then re-submit the form
+                               $resetForm.off( 'submit' ).submit();
                        } );
                } );
 
index 4d90496..2fe5d3d 100644 (file)
@@ -5,6 +5,8 @@
  * @license The MIT License (MIT); see LICENSE.txt
  */
 
+@import 'mediawiki.mixins';
+
 @calendarWidth: 21em;
 @calendarHeight: 14em;
 
@@ -14,7 +16,7 @@
 
 .mw-widget-calendarWidget-header {
        position: relative;
-       line-height: 2.5em;
+       line-height: 2.5;
 }
 
 .mw-widget-calendarWidget-header .oo-ui-buttonWidget {
                height: @calendarHeight;
        }
 
-       .mw-widget-calendarWidget-old-body {
-               // background: #fdd;
-       }
-
-       .mw-widget-calendarWidget-body:not(.mw-widget-calendarWidget-old-body):first-child {
+       .mw-widget-calendarWidget-body:not( .mw-widget-calendarWidget-old-body ):first-child {
                margin-top: -@calendarHeight;
                margin-left: -@calendarWidth;
        }
 
-       .mw-widget-calendarWidget-body:not(.mw-widget-calendarWidget-old-body):last-child {
+       .mw-widget-calendarWidget-body:not( .mw-widget-calendarWidget-old-body ):last-child {
                margin-top: 0;
                margin-left: 0;
        }
@@ -86,7 +84,7 @@
        .mw-widget-calendarWidget-body:first-child {
                margin-top: 0 !important;
                margin-left: 0 !important;
-               transition: 0.5s margin-left;
+               .transition( margin-left 500ms );
        }
 }
 
@@ -97,7 +95,7 @@
        .mw-widget-calendarWidget-body:first-child {
                margin-left: -@calendarWidth !important;
                margin-top: 0 !important;
-               transition: 0.5s margin-left;
+               .transition( margin-left 500ms );
        }
 }
 
        .mw-widget-calendarWidget-body:first-child {
                margin-left: 0 !important;
                margin-top: 0 !important;
-               transition: 0.5s margin-top;
+               .transition( margin-top 500ms );
        }
 }
 
        .mw-widget-calendarWidget-body:first-child {
                margin-left: 0 !important;
                margin-top: -@calendarHeight !important;
-               transition: 0.5s margin-top;
+               .transition( margin-top 500ms );
        }
 }
 
        width: @calendarWidth / 7;
        line-height: @calendarHeight / 7;
        // Don't overlap the hacked-up fake box-shadow border we get when focussed
-       &:nth-child(7n) {
+       &:nth-child( 7n ) {
                width: @calendarWidth / 7 - 0.2em;
                margin-right: 0.2em;
        }
-       &:nth-child(7n+1) {
+       &:nth-child( 7n+1 ) {
                width: @calendarWidth / 7 - 0.2em;
                margin-left: 0.2em;
        }
-       &:nth-child(42) ~ & {
+       &:nth-child( 42 ) ~ & {
                line-height: @calendarHeight / 7 - 0.2em;
                margin-bottom: 0.2em;
        }
        width: @calendarWidth / 2;
        line-height: @calendarHeight / 6;
        // Don't overlap the hacked-up fake box-shadow border we get when focussed
-       &:nth-child(2n) {
+       &:nth-child( 2n ) {
                width: @calendarWidth / 2 - 0.2em;
                margin-right: 0.2em;
        }
-       &:nth-child(2n+1) {
+       &:nth-child( 2n+1 ) {
                width: @calendarWidth / 2 - 0.2em;
                margin-left: 0.2em;
        }
-       &:nth-child(10) ~ & {
+       &:nth-child( 10 ) ~ & {
                line-height: @calendarHeight / 6 - 0.2em;
                margin-bottom: 0.2em;
        }
        width: @calendarWidth / 5;
        line-height: @calendarHeight / 4;
        // Don't overlap the hacked-up fake box-shadow border we get when focussed
-       &:nth-child(5n) {
+       &:nth-child( 5n ) {
                width: @calendarWidth / 5 - 0.2em;
                margin-right: 0.2em;
        }
-       &:nth-child(5n+1) {
+       &:nth-child( 5n+1 ) {
                width: @calendarWidth / 5 - 0.2em;
                margin-left: 0.2em;
        }
-       &:nth-child(15) ~ & {
+       &:nth-child( 15 ) ~ & {
                line-height: @calendarHeight / 4 - 0.2em;
                margin-bottom: 0.2em;
        }
 
 /* Theme-specific */
 .mw-widget-calendarWidget {
-       box-shadow: inset 0 0 0 1px #ccc;
-}
+       .box-sizing( border-box );
+       border: 1px solid #a2a9b1;
+       .transition( ~'border-color 100ms, box-shadow 100ms' );
 
-.mw-widget-calendarWidget:focus {
-       outline: none;
-       box-shadow: inset 0 0 0 2px #36c;
-}
+       &:focus {
+               border-color: #36c;
+               box-shadow: inset 0 0 0 1px #36c;
+               outline: 0;
+       }
 
-.mw-widget-calendarWidget-day {
-       color: #444;
-       border-radius: 0.1em;
-}
+       &-day {
+               color: #222;
+               border-radius: 2px;
+       }
 
-.mw-widget-calendarWidget-day-heading {
-       font-weight: bold;
-       color: #555;
-}
+       &-day-heading {
+               color: #54595d;
+               font-weight: bold;
+       }
 
-.mw-widget-calendarWidget-day-additional {
-       color: #aaa;
-}
+       &-day-additional {
+               color: #a2a9b1;
 
-.mw-widget-calendarWidget-day-today {
-       box-shadow: inset 0 0 0 1px #3787fb;
-}
+               &:hover {
+                       color: #222;
+               }
+       }
 
-.mw-widget-calendarWidget-item-selected {
-       background-color: #d8e6fe;
-       color: #3787fb;
-}
+       &-day-today {
+               box-shadow: inset 0 0 0 1px #36c;
+       }
+
+       &-item {
+               .transition( ~'background-color 250ms, color 250ms' );
 
-.mw-widget-calendarWidget-item:hover {
-       background-color: #eee;
+               &:hover {
+                       background-color: #36c;
+                       color: #fff;
+               }
+
+               &-selected {
+                       background-color: #2a4b8d;
+                       color: #fff;
+               }
+       }
 }
index 46e6b62..8ba9a99 100644 (file)
@@ -21,6 +21,7 @@
 
 .oo-ui-inline-spacing( @spacing, @cancelled-spacing: 0 ) {
        margin-right: @spacing;
+
        &:last-child {
                margin-right: @cancelled-spacing;
        }
 .mw-widget-dateInputWidget {
        display: inline-block;
        position: relative;
+       width: 21em;
+       margin-top: 0.25em;
+       .oo-ui-inline-spacing( 0.5em );
+       margin-bottom: 0.25em;
+       margin-left: 0;
 
        &-handle {
-               width: 100%;
+               background-color: #fff;
                display: inline-block;
-               cursor: pointer;
                position: relative;
-
+               .oo-ui-box-sizing( border-box );
+               width: 100%;
                .oo-ui-unselectable();
-               .oo-ui-box-sizing(border-box);
+               cursor: pointer;
+               padding: 0.5em 1em;
+               border: 1px solid #a2a9b1;
+               border-radius: 2px;
+               outline: 0;
+               line-height: 1.275;
+
+               > .oo-ui-labelElement-label {
+                       padding: 0;
+               }
 
                > .oo-ui-indicatorElement-indicator {
                        display: none;
                position: absolute;
                top: 0;
                right: 0;
-               height: 100%;
-       }
-
-       &.oo-ui-widget-disabled .mw-widget-dateInputWidget-handle {
-               cursor: default;
-       }
-
-       &-calendar {
-               position: absolute;
-               z-index: 1;
-       }
-
-       // Theme-specific styles
-       width: 21em;
-       margin: 0.25em 0;
-
-       .oo-ui-inline-spacing(0.5em);
-
-       &-handle {
-               padding: 0.5em 1em;
-               border: 1px solid #ccc;
-               border-radius: 0.1em;
-               line-height: 1.275em;
-               background-color: #fff;
-
-               > .oo-ui-labelElement-label {
-                       padding: 0;
-               }
-       }
-
-       &.oo-ui-indicatorElement .mw-widget-dateInputWidget-handle > .oo-ui-indicatorElement-indicator {
                width: @indicator-size;
+               height: 100%;
                margin: 0 0.775em;
        }
 
-       > .oo-ui-textInputWidget input {
-               padding-left: 1em;
-       }
-
        > .oo-ui-textInputWidget {
                z-index: 2;
+
+               & input {
+                       padding-left: 1em;
+               }
        }
 
        &-calendar {
                background-color: #fff;
+               position: absolute;
                margin-top: -2px;
+               box-shadow: 0 0.15em 0 0 rgba( 0, 0, 0, 0.15 );
+               z-index: 1;
 
                &:focus {
+                       box-shadow: inset 0 0 0 1px #36c, 0 0.15em 0 0 rgba( 0, 0, 0, 0.15 );
                        z-index: 3;
                }
        }
 
-       &.oo-ui-widget-enabled {
-               .mw-widget-dateInputWidget-handle:hover {
-                       border-color: #36c;
-               }
-       }
-
-       &.oo-ui-widget-disabled {
+       &-empty {
                .mw-widget-dateInputWidget-handle {
-                       color: #ccc;
-                       text-shadow: 0 1px 1px #fff;
-                       border-color: #ddd;
-                       background-color: #f3f3f3;
-
-                       > .oo-ui-indicatorElement-indicator {
-                               opacity: 0.2;
-                       }
+                       color: #54595d;
+                       outline: 0;
                }
-
        }
 
        &.oo-ui-flaggedElement-invalid {
                }
        }
 
-       &-empty {
+       &.oo-ui-widget-enabled {
+               .mw-widget-dateInputWidget-handle:hover {
+                       border-color: #72777d;
+               }
+       }
+
+       &.oo-ui-widget-disabled {
                .mw-widget-dateInputWidget-handle {
-                       color: #ccc;
+                       background-color: #eaecf0;
+                       color: #72777d;
+                       border-color: #c8ccd1;
+                       text-shadow: 0 1px 1px #fff;
+                       cursor: default;
+
+                       > .oo-ui-indicatorElement-indicator {
+                               opacity: 0.51;
+                       }
                }
        }
 }
index 2ac75c5..0a73bef 100755 (executable)
@@ -34,7 +34,8 @@
                        icon: 'search',
                        maxLength: undefined,
                        performSearchOnClick: true,
-                       dataLocation: 'header'
+                       dataLocation: 'header',
+                       namespace: 0
                }, config );
 
                // Parent constructor
@@ -83,7 +84,7 @@
                        self = this;
 
                // reuse the searchSuggest function from mw.searchSuggest
-               promise = mw.searchSuggest.request( api, this.getQueryValue(), $.noop, this.limit );
+               promise = mw.searchSuggest.request( api, this.getQueryValue(), $.noop, this.limit, this.getNamespace() );
 
                // tracking purposes
                promise.done( function ( data, jqXHR ) {
index 0e5e0c5..3a4581d 100644 (file)
                        cache[ key ] = api.get( {
                                action: 'query',
                                meta: 'siteinfo',
-                               siprop: 'interwikimap'
+                               siprop: 'interwikimap',
+                               // Cache client-side for a day since this info is mostly static
+                               maxage: 60 * 60 * 24,
+                               smaxage: 60 * 60 * 24,
+                               // Workaround T97096 by setting uselang=content
+                               uselang: 'content'
                        } ).then( function ( data ) {
                                return $.map( data.query.interwikimap, function ( interwiki ) {
                                        return interwiki.prefix;
index b9db059..a174f58 100644 (file)
                                                        jqXHR
                                                );
                                        } else if ( result.error ) {
+                                               // errorformat=bc
                                                code = result.error.code === undefined ? 'unknown' : result.error.code;
                                                apiDeferred.reject( code, result, result, jqXHR );
                                        } else if ( result.errors ) {
+                                               // errorformat!=bc
                                                code = result.errors[ 0 ].code === undefined ? 'unknown' : result.errors[ 0 ].code;
                                                apiDeferred.reject( code, result, result, jqXHR );
                                        } else {
index 92722b5..5299252 100644 (file)
@@ -26,9 +26,9 @@
                var apiPromise = this.postWithToken( 'watch',
                        $.extend(
                                {
+                                       formatversion: 2,
                                        action: 'watch',
-                                       titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages ),
-                                       uselang: mw.config.get( 'wgUserLanguage' )
+                                       titles: $.isArray( pages ) ? pages.join( '|' ) : String( pages )
                                },
                                addParams
                        )
index 5f60097..f9cb5de 100644 (file)
        }
 
        mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
-               $root.find( '.mw-htmlform-hide-if' ).each( function () {
-                       var v, i, fields, test, func, spec, self, modules, data, extraModules,
-                               $el = $( this );
-
+               var
+                       $fields = $root.find( '.mw-htmlform-hide-if' ),
+                       $oouiFields = $fields.filter( '[data-ooui]' ),
                        modules = [];
-                       if ( $el.is( '[data-ooui]' ) ) {
-                               modules.push( 'mediawiki.htmlform.ooui' );
+
+               if ( $oouiFields.length ) {
+                       modules.push( 'mediawiki.htmlform.ooui' );
+                       $oouiFields.each( function () {
+                               var data, extraModules,
+                                       $el = $( this );
+
                                data = $el.data( 'mw-modules' );
                                if ( data ) {
                                        // We can trust this value, 'data-mw-*' attributes are banned from user content in Sanitizer
                                        extraModules = data.split( ',' );
                                        modules.push.apply( modules, extraModules );
                                }
-                       }
+                       } );
+               }
+
+               mw.loader.using( modules ).done( function () {
+                       $fields.each( function () {
+                               var v, i, fields, test, func, spec, self,
+                                       $el = $( this );
 
-                       mw.loader.using( modules ).done( function () {
                                if ( $el.is( '[data-ooui]' ) ) {
                                        // self should be a FieldLayout that mixes in mw.htmlform.Element
                                        self = OO.ui.FieldLayout.static.infuse( $el );
                                test = v[ 1 ];
                                // The .toggle() method works mostly the same for jQuery objects and OO.ui.Widget
                                func = function () {
-                                       self.toggle( !test() );
+                                       var shouldHide = test();
+                                       self.toggle( !shouldHide );
+
+                                       // It is impossible to submit a form with hidden fields failing validation, e.g. one that
+                                       // is required. However, validity is not checked for disabled fields, as these are not
+                                       // submitted with the form. So we should also disable fields when hiding them.
+                                       if ( self instanceof jQuery ) {
+                                               // This also finds elements inside any nested fields (in case of HTMLFormFieldCloner),
+                                               // which is problematic. But it works because:
+                                               // * HTMLFormFieldCloner::createFieldsForKey() copies 'hide-if' rules to nested fields
+                                               // * jQuery collections like $fields are in document order, so we register event
+                                               //   handlers for parents first
+                                               // * Event handlers are fired in the order they were registered, so even if the handler
+                                               //   for parent messed up the child, the handle for child will run next and fix it
+                                               self.find( 'input, textarea, select' ).each( function () {
+                                                       var $this = $( this );
+                                                       if ( shouldHide ) {
+                                                               if ( $this.data( 'was-disabled' ) === undefined ) {
+                                                                       $this.data( 'was-disabled', $this.prop( 'disabled' ) );
+                                                               }
+                                                               $this.prop( 'disabled', true );
+                                                       } else {
+                                                               $this.prop( 'disabled', $this.data( 'was-disabled' ) );
+                                                       }
+                                               } );
+                                       } else {
+                                               // self is a OO.ui.FieldLayout
+                                               if ( shouldHide ) {
+                                                       if ( self.wasDisabled === undefined ) {
+                                                               self.wasDisabled = self.fieldWidget.isDisabled();
+                                                       }
+                                                       self.fieldWidget.setDisabled( false );
+                                               } else if ( self.wasDisabled !== undefined ) {
+                                                       self.fieldWidget.setDisabled( self.wasDisabled );
+                                               }
+                                       }
                                };
                                for ( i = 0; i < fields.length; i++ ) {
                                        // The .on() method works mostly the same for jQuery objects and OO.ui.Widget
index 1603130..1b9d2fb 100644 (file)
@@ -1,5 +1,9 @@
 /* HTMLForm styles */
 
+.mw-htmlform {
+       clear: both;
+}
+
 table.mw-htmlform-nolabel td.mw-label {
        display: none;
 }
index fa1a78c..bcb6c33 100644 (file)
@@ -4,12 +4,12 @@
 ( function ( mw, $ ) {
        mw.searchSuggest = {
                // queries the wiki and calls response with the result
-               request: function ( api, query, response, maxRows ) {
+               request: function ( api, query, response, maxRows, namespace ) {
                        return api.get( {
                                formatversion: 2,
                                action: 'opensearch',
                                search: query,
-                               namespace: 0,
+                               namespace: namespace || 0,
                                limit: maxRows,
                                suggest: true
                        } ).done( function ( data, jqXHR ) {
@@ -22,7 +22,7 @@
        };
 
        $( function () {
-               var api, map, searchboxesSelectors,
+               var api, searchboxesSelectors,
                        // Region where the suggestions box will appear directly below
                        // (using the same width). Can be a container element or the input
                        // itself, depending on what suits best in the environment.
                        $searchInput = $( '#searchInput' ),
                        previousSearchText = $searchInput.val();
 
-               // Compatibility map
-               map = {
-                       // SimpleSearch is broken in Opera < 9.6
-                       opera: [ [ '>=', 9.6 ] ],
-                       // Older Konquerors are unable to position the suggestions correctly (bug 50805)
-                       konqueror: [ [ '>=', '4.11' ] ],
-                       docomo: false,
-                       blackberry: false,
-                       // Support for iOS 6 or higher. It has not been tested on iOS 5 or lower
-                       ipod: [ [ '>=', 6 ] ],
-                       iphone: [ [ '>=', 6 ] ]
-               };
-
-               if ( !$.client.test( map ) ) {
-                       return;
-               }
-
                // Compute form data for search suggestions functionality.
                function getFormData( context ) {
                        var $form, baseHref, linkParams;
index 0319c64..5dda7e0 100644 (file)
                                .done( function ( watchResponse ) {
                                        var mwTitle, message, otherAction = action === 'watch' ? 'unwatch' : 'watch';
 
-                                       message = action === 'watch' ? 'addedwatchtext' : 'removedwatchtext';
                                        mwTitle = mw.Title.newFromText( title );
-                                       if ( mwTitle && mwTitle.getNamespaceId() > 0 &&
-                                               /* eslint-disable no-bitwise */
-                                               ( mwTitle.getNamespaceId() & 1 ) === 1
-                                               /* eslint-enable no-bitwise */
-                                       ) {
-                                               message += '-talk';
+                                       if ( mwTitle && mwTitle.getNamespaceId() > 0 && mwTitle.getNamespaceId() % 2 === 1 ) {
+                                               message = action === 'watch' ? 'addedwatchtext-talk' : 'removedwatchtext-talk';
+                                       } else {
+                                               message = action === 'watch' ? 'addedwatchtext' : 'removedwatchtext';
                                        }
 
                                        mw.notify( mw.message( message, title ).parseDom(), {
 
                                        // Update the "Watch this page" checkbox on action=edit when the
                                        // page is watched or unwatched via the tab (bug 12395).
-                                       $( '#wpWatchthis' ).prop( 'checked', watchResponse.watched !== undefined );
+                                       $( '#wpWatchthis' ).prop( 'checked', watchResponse.watched === true );
                                } )
                                .fail( function () {
                                        var cleanTitle, msg, link;
index 82a00bc..20818d2 100644 (file)
@@ -75,7 +75,7 @@ function isCompatible( str ) {
                // support in the modern run-time.
                // Note: Please extend the regex instead of adding new ones
                !(
-                       ua.match( /webOS\/1\.[0-4]|SymbianOS|Series60|NetFront|Opera Mini|S40OviBrowser|MeeGo|Android.+Glass|^Mozilla\/5\.0 .+ Gecko\/$/ ) ||
+                       ua.match( /webOS\/1\.[0-4]|SymbianOS|Series60|NetFront|Opera Mini|S40OviBrowser|MeeGo|Android.+Glass|^Mozilla\/5\.0 .+ Gecko\/$|googleweblight/ ) ||
                        ua.match( /PlayStation/i )
                )
        );
index 5b17eac..b6f2830 100644 (file)
@@ -271,6 +271,12 @@ Template:EmptyTRWithHTMLAttrTest
 </table>
 !!endarticle
 
+!! article
+Template:CircularRef
+!! text
+<ref>{{CircularRef}}</ref>
+!! endarticle
+
 ###
 ### Basic tests
 ###
@@ -280,6 +286,15 @@ Blank input
 !! html
 !! end
 
+!! test
+CircularRef
+!! wikitext
+{{CircularRef}}
+<references />
+!! html/parsoid
+<p><span about="#mwt1" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-parsoid='{"pi":[[]]}' data-mw='{"parts":[{"template":{"target":{"wt":"CircularRef","href":"./Template:CircularRef"},"params":{},"i":0}}]}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></p>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">Error: Expansion loop detected at <a data-parsoid='{"a":{"href":null},"sa":{"href":"Template:CircularRef"}}'>Template:CircularRef</a></span></li></ol>
+!! end
 
 !! test
 Simple paragraph
@@ -513,6 +528,17 @@ Extra newlines between heading and content are swallowed
 </p>
 !! end
 
+!! test
+Heading with line break in nowiki
+!! wikitext
+== A <nowiki>B
+C</nowiki> ==
+!! html
+<h2><span class="mw-headline" id="A_B.0AC">A B
+C</span><span class="mw-editsection"><span class="mw-editsection-bracket">[</span><a href="/index.php?title=Parser_test&amp;action=edit&amp;section=1" title="Edit section: A B&#10;C">edit</a><span class="mw-editsection-bracket">]</span></span></h2>
+
+!! end
+
 !! test
 Parsing an URL
 !! wikitext
@@ -1427,6 +1453,8 @@ Don't parse <nowiki><span class="error"></nowiki> (T149622)
 !! html/php
 <p>&lt;span class="error"&gt;
 </p>
+!! html/parsoid
+<p><span typeof="mw:Nowiki">&lt;span class="error"></span></p>
 !! end
 
 !! test
@@ -2727,6 +2755,10 @@ Templates: Handle comments in the target
 <!-- should be ignored -->
 |foo}}
 
+{{echo
+<!-- should be ignored and spaces on next line should not trip us up (T147742) -->
+  |foo}}
+
 {{echo<!-- should be ignored -->
 |foo}}
 
@@ -2738,10 +2770,13 @@ Templates: Handle comments in the target
 </p><p>foo
 </p><p>foo
 </p><p>foo
+</p><p>foo
 </p>
 !! html/parsoid
 <p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo\n&lt;!-- should be ignored -->\n","href":"./Template:Echo"},"params":{"1":{"wt":"foo"}},"i":0}}]}'>foo</p>
 
+<p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo\n&lt;!-- should be ignored and spaces on next line should not trip us up (T147742) -->\n  ","href":"./Template:Echo"},"params":{"1":{"wt":"foo"}},"i":0}}]}'>foo</p>
+
 <p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo&lt;!-- should be ignored -->\n","href":"./Template:Echo"},"params":{"1":{"wt":"foo"}},"i":0}}]}'>foo</p>
 
 <p typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo&lt;!-- should be ignored -->","href":"./Template:Echo"},"params":{"1":{"wt":"foo"}},"i":0}}]}'>foo</p>
@@ -3686,7 +3721,6 @@ Definition and unordered list using wiki syntax nested in unordered list using h
 !! end
 
 !! test
-
 Definition list with empty definition and following paragraph
 !! wikitext
 ; term:
@@ -6442,6 +6476,18 @@ parsoid=wt2html,html2html
 <span typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"ho\">ha&lt;/div>"}},"i":0}}]}'>ho">ha</span>
 !! end
 
+!! test
+Don't break on | in extension attribute in template
+!! wikitext
+{{echo|<ref name="hi|ho">ha</ref>}}
+
+<references />
+!! html/parsoid
+<p><span about="#mwt2" class="mw-ref" id="cite_ref-hi.7Cho_1-0" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-parsoid='{"pi":[[{"k":"1"}]]}' data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;ref name=\"hi|ho\">ha&lt;/ref>"}},"i":0}}]}'><a href="./Main_Page#cite_note-hi.7Cho-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></p>
+
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-hi.7Cho-1" id="cite_note-hi.7Cho-1"><a href="./Main_Page#cite_ref-hi.7Cho_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-hi.7Cho-1" class="mw-reference-text">ha</span></li></ol>
+!! end
+
 ## We don't support roundtripping of these attributes in Parsoid.
 ## Selective serialization takes care of preventing dirty diffs.
 ## But, on edits, we dirty-diff the invalid attribute text.
@@ -6612,9 +6658,9 @@ T107652: <ref>s in templates that also generate table cell attributes should be
 <references />
 !! html/parsoid
 <table>
-<tbody><tr><td style="background:#f9f9f9;" typeof="mw:Transclusion" about="#mwt1" data-mw='{"parts":["|",{"template":{"target":{"wt":"table_attribs_7","href":"./Template:Table_attribs_7"},"params":{},"i":0}}]}'>Foo<span class="mw-ref" id="cite_ref-1" rel="dc:references" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></td></tr>
+<tbody><tr><td style="background:#f9f9f9;" typeof="mw:Transclusion" about="#mwt1" data-mw='{"parts":["|",{"template":{"target":{"wt":"table_attribs_7","href":"./Template:Table_attribs_7"},"params":{},"i":0}}]}'>Foo<span class="mw-ref" id="cite_ref-1" rel="dc:references" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></td></tr>
 </tbody></table>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
 !! end
 
 !! test
@@ -7596,8 +7642,6 @@ Link with multiple pipes
 </p>
 !! end
 
-# Note that parsoid does not munge anchor text; all non-space
-# characters are valid in HTML5 ids.
 !! test
 Anchor containing a #. (bug 63430)
 !! wikitext
@@ -7606,7 +7650,7 @@ Anchor containing a #. (bug 63430)
 <p><a href="/wiki/Main_Page#And.23Link" title="Main Page">Main Page#And#Link</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main_Page#And%23Link" title="Main Page">Main Page#And#Link</a></p>
+<p><a rel="mw:WikiLink" href="./Main_Page#And.23Link" title="Main Page" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#And.23Link"},"sa":{"href":"Main Page#And#Link"}}'>Main Page#And#Link</a></p>
 !! end
 
 !! test
@@ -7721,18 +7765,16 @@ Link containing % as a double hex sequence interpreted to hex sequence
 </p>
 !!end
 
-# note that parsoid does not munge anchor text; all non-space
-# characters are valid in HTML5 anchors.
+## Example for such a section: == < ==
 !! test
 Link containing "#<" and "#>" % as a hex sequences- these are valid section anchors
-Example for such a section: == < ==
 !! wikitext
 [[%23%3c]][[%23%3e]]
 !! html/php
 <p><a href="#.3C">#&lt;</a><a href="#.3E">#&gt;</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Main_Page#%3C" title="Main Page">#&lt;</a><a rel="mw:WikiLink" href="./Main_Page#%3E" title="Main Page">#></a></p>
+<p><a rel="mw:WikiLink" href="./Main_Page#.3C" title="Main Page" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#.3C"},"sa":{"href":"%23%3c"}}'>#&lt;</a><a rel="mw:WikiLink" href="./Main_Page#.3E" title="Main Page" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#.3E"},"sa":{"href":"%23%3e"}}'>#></a></p>
 !! end
 
 !! test
@@ -8252,7 +8294,7 @@ Link with angle bracket after anchor
 <p><a href="/wiki/Foo#.3Cbar.3E" title="Foo">Foo#&lt;bar&gt;</a>
 </p>
 !! html/parsoid
-<p><a rel="mw:WikiLink" href="./Foo#%3Cbar%3E" title="Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo#%3Cbar%3E"},"sa":{"href":"Foo#&lt;bar>"}}'>Foo#&lt;bar></a></p>
+<p><a rel="mw:WikiLink" href="./Foo#.3Cbar.3E" title="Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo#.3Cbar.3E"},"sa":{"href":"Foo#&lt;bar>"}}'>Foo#&lt;bar></a></p>
 !! end
 
 ###
@@ -8310,6 +8352,23 @@ Interwiki link with fragment (bug 2130)
 </p>
 !! end
 
+!! test
+Link scenarios with escaped fragments
+!! wikitext
+[[#Is this great?]]
+[[Foo#Is this great?]]
+[[meatball:Foo#Is this great?]]
+!! html/php
+<p><a href="#Is_this_great.3F">#Is this great?</a>
+<a href="/wiki/Foo#Is_this_great.3F" title="Foo">Foo#Is this great?</a>
+<a href="http://www.usemod.com/cgi-bin/mb.pl?Foo#Is_this_great.3F" class="extiw" title="meatball:Foo">meatball:Foo#Is this great?</a>
+</p>
+!! html/parsoid
+<p><a rel="mw:WikiLink" href="./Main_Page#Is_this_great.3F" data-parsoid='{"stx":"simple","a":{"href":"./Main_Page#Is_this_great.3F"},"sa":{"href":"#Is this great?"}}'>#Is this great?</a>
+<a rel="mw:WikiLink" href="./Foo#Is_this_great.3F" title="Foo" data-parsoid='{"stx":"simple","a":{"href":"./Foo#Is_this_great.3F"},"sa":{"href":"Foo#Is this great?"}}'>Foo#Is this great?</a>
+<a rel="mw:ExtLink" href="http://www.usemod.com/cgi-bin/mb.pl?Foo#Is_this_great.3F" title="meatball:Foo" data-parsoid='{"stx":"simple","a":{"href":"http://www.usemod.com/cgi-bin/mb.pl?Foo#Is_this_great.3F"},"sa":{"href":"meatball:Foo#Is this great?"},"isIW":true}'>meatball:Foo#Is this great?</a></p>
+!! end
+
 # Ideally the wikipedia: prefix here should be proto-relative too
 # [CSA]: this is kind of a bogus test, as the PHP parser test doesn't
 # define the 'en' prefix, and originally the test used 'wikipedia',
@@ -10374,7 +10433,6 @@ language=de
 </p>
 !! end
 
-
 !! test
 Urlencode
 !! wikitext
@@ -10382,7 +10440,7 @@ Urlencode
 {{urlencode:hi world?!|WIKI}}
 {{urlencode:hi world?!|PATH}}
 {{urlencode:hi world?!|QUERY}}
-!! html
+!! html/php
 <p>hi+world%3F%21
 hi_world%3F!
 hi%20world%3F%21
@@ -12252,11 +12310,11 @@ Templates: Wiki Tables: 7. Fosterable <ref>s should get fostered
 
 <references />
 !!html/parsoid
-<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"PartialTable","href":"./Template:PartialTable"},"params":{},"i":0}},"&lt;ref>foo&lt;/ref>\n|}"]}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span><table about="#mwt2">
+<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"PartialTable","href":"./Template:PartialTable"},"params":{},"i":0}},"&lt;ref>foo&lt;/ref>\n|}"]}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span><table about="#mwt2">
 <tbody>
 </tbody></table>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
 !!end
 
 !! test
@@ -14110,6 +14168,19 @@ Escape HTML special chars in image alt text
 <p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"caption","ak":"&amp; &lt; > \""}]}' data-mw='{"caption":"&amp;amp; &amp;lt; > \""}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 !! end
 
+!! test
+Escape HTML special chars in image alt text with LanguageConverter
+!! options
+language=zh
+!! wikitext
+[[File:Foobar.jpg|& < > "]]
+!! html/php
+<p><a href="/wiki/File:Foobar.jpg" class="image" title="&amp; &lt; &gt; &quot;"><img alt="&amp; &lt; &gt; &quot;" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+</p>
+!! html/parsoid
+<p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"caption","ak":"&amp; &lt; > \""}]}' data-mw='{"caption":"&amp;amp; &amp;lt; > \""}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+!! end
+
 !! test
 Entities in file name and attributes
 !! wikitext
@@ -14549,9 +14620,9 @@ T93580: 1. Templated <ref> inside block images
 
 <references />
 !! html/parsoid
-<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption with templated ref: {{echo|&lt;ref>foo&lt;/ref>}}"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>Caption with templated ref: <span about="#mwt5" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;ref>foo&lt;/ref>"}},"i":0}}]}'><a href="#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></figcaption></figure>
+<figure class="mw-default-size" typeof="mw:Image/Thumb" data-parsoid='{"optList":[{"ck":"thumbnail","ak":"thumb"},{"ck":"caption","ak":"Caption with templated ref: {{echo|&lt;ref>foo&lt;/ref>}}"}]}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"25","width":"220"},"sa":{"resource":"File:Foobar.jpg"}}'/></a><figcaption>Caption with templated ref: <span about="#mwt5" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;ref>foo&lt;/ref>"}},"i":0}}]}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></figcaption></figure>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
 !! end
 
 !! test
@@ -14561,9 +14632,9 @@ T93580: 2. <ref> inside inline images
 
 <references />
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"caption","ak":"Undisplayed caption in inline image with ref: &lt;ref>foo&lt;/ref>"}]}' data-mw='{"caption":"Undisplayed caption in inline image with ref: &lt;span about=\"#mwt2\" class=\"mw-ref\" id=\"cite_ref-1\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[64,78,5,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-1\"},\"attrs\":{}}&#39;>&lt;a href=\"#cite_note-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]&lt;/span>&lt;/a>&lt;/span>&lt;meta typeof=\"mw:Extension/ref/Marker\" about=\"#mwt2\" data-parsoid=&#39;{\"group\":\"\",\"name\":\"\",\"content\":\"foo\",\"hasRefInRef\":false,\"dsr\":[64,78,5,6]}&#39;/>"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"caption","ak":"Undisplayed caption in inline image with ref: &lt;ref>foo&lt;/ref>"}]}' data-mw='{"caption":"Undisplayed caption in inline image with ref: &lt;span about=\"#mwt2\" class=\"mw-ref\" id=\"cite_ref-1\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[64,78,5,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-1\"},\"attrs\":{}}&#39;>&lt;a href=\"./Main_Page#cite_note-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]&lt;/span>&lt;/a>&lt;/span>&lt;meta typeof=\"mw:Extension/ref/Marker\" about=\"#mwt2\" data-parsoid=&#39;{\"group\":\"\",\"name\":\"\",\"content\":\"foo\",\"hasRefInRef\":false,\"dsr\":[64,78,5,6]}&#39;/>"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
 !! end
 
 !! test
@@ -14573,9 +14644,9 @@ T93580: 3. Templated <ref> inside inline images
 
 <references />
 !! html/parsoid
-<p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"caption","ak":"Undisplayed caption in inline image with ref: {{echo|&lt;ref>{{echo|foo}}&lt;/ref>}}"}]}' data-mw='{"caption":"Undisplayed caption in inline image with ref: &lt;span about=\"#mwt2\" class=\"mw-ref\" id=\"cite_ref-1\" rel=\"dc:references\" typeof=\"mw:Transclusion  mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[64,96,null,null],\"pi\":[[{\"k\":\"1\"}]]}&#39; data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&amp;lt;ref>{{echo|foo}}&amp;lt;/ref>\"}},\"i\":0}}]}&#39;>&lt;a href=\"#cite_note-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]&lt;/span>&lt;/a>&lt;/span>&lt;meta typeof=\"mw:Transclusion mw:Extension/ref/Marker\" about=\"#mwt2\" data-parsoid=&#39;{\"group\":\"\",\"name\":\"\",\"content\":\"foo\",\"hasRefInRef\":false,\"dsr\":[64,96,null,null],\"pi\":[[{\"k\":\"1\"}]]}&#39; data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&amp;lt;ref>{{echo|foo}}&amp;lt;/ref>\"}},\"i\":0}}]}&#39;/>"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
+<p><span class="mw-default-size" typeof="mw:Image" data-parsoid='{"optList":[{"ck":"caption","ak":"Undisplayed caption in inline image with ref: {{echo|&lt;ref>{{echo|foo}}&lt;/ref>}}"}]}' data-mw='{"caption":"Undisplayed caption in inline image with ref: &lt;span about=\"#mwt2\" class=\"mw-ref\" id=\"cite_ref-1\" rel=\"dc:references\" typeof=\"mw:Transclusion  mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[64,96,null,null],\"pi\":[[{\"k\":\"1\"}]]}&#39; data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&amp;lt;ref>{{echo|foo}}&amp;lt;/ref>\"}},\"i\":0}}]}&#39;>&lt;a href=\"./Main_Page#cite_note-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]&lt;/span>&lt;/a>&lt;/span>&lt;meta typeof=\"mw:Transclusion mw:Extension/ref/Marker\" about=\"#mwt2\" data-parsoid=&#39;{\"group\":\"\",\"name\":\"\",\"content\":\"foo\",\"hasRefInRef\":false,\"dsr\":[64,96,null,null],\"pi\":[[{\"k\":\"1\"}]]}&#39; data-mw=&#39;{\"parts\":[{\"template\":{\"target\":{\"wt\":\"echo\",\"href\":\"./Template:Echo\"},\"params\":{\"1\":{\"wt\":\"&amp;lt;ref>{{echo|foo}}&amp;lt;/ref>\"}},\"i\":0}}]}&#39;/>"}'><a href="./File:Foobar.jpg" data-parsoid='{"a":{"href":"./File:Foobar.jpg"},"sa":{}}'><img resource="./File:Foobar.jpg" src="//example.com/images/3/3a/Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="220" width="1941" data-parsoid='{"a":{"resource":"./File:Foobar.jpg","height":"220","width":"1941"},"sa":{"resource":"File:Foobar.jpg"}}'/></a></span></p>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo</span></li></ol>
 !! end
 
 ###
@@ -15929,7 +16000,7 @@ parsoid=wt2html,html2html
 <div id="title.3D">HTML rocks</div>
 
 !! html/parsoid
-<div id="title=" data-parsoid='{"stx":"html"}'>HTML rocks</div>
+<div id="title.3D" data-parsoid='{"stx":"html"}'>HTML rocks</div>
 !! end
 
 !! test
@@ -17107,9 +17178,11 @@ Table not started</td></tr></table>
 Sanitizer: Escaping of spaces, multibyte characters, colons & other stuff in id=""
 !! wikitext
 <span id="æ: v">byte</span>[[#æ: v|backlink]]
-!! html
+!! html/php
 <p><span id=".C3.A6:_v">byte</span><a href="#.C3.A6:_v">backlink</a>
 </p>
+!! html/parsoid
+<p><span id=".C3.A6:_v" data-parsoid='{"stx":"html","a":{"id":".C3.A6:_v"},"sa":{"id":"æ: v"}}'>byte</span><a rel="mw:WikiLink" href="./Main_Page#.C3.A6:_v" data-parsoid='{"stx":"piped","a":{"href":"./Main_Page#.C3.A6:_v"},"sa":{"href":"#æ: v"}}'>backlink</a></p>
 !! end
 
 # In HTML5, the restrictions are that id must contain at least one character,
@@ -18858,8 +18931,14 @@ title=[[Parser test]]
 !! end
 ### Note: Above tests excludes the "{{NUMBEROFADMINS}}" magic word because it generates a MySQL error when included.
 
+## Parsoid thinks the "centre" here is a property, not a caption.
 !! test
 Gallery
+!! options
+parsoid={
+  "modes": ["wt2html"],
+  "nativeGallery": true
+}
 !! wikitext
 <gallery>
 image1.png |
@@ -18871,7 +18950,7 @@ image4    |300px| centre
 [[x|xx]]]]
 * image6
 </gallery>
-!! html
+!! html/php
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="height: 150px;">Image1.png</div>
@@ -18909,19 +18988,33 @@ image4    |300px| centre
                </div></li>
 </ul>
 
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt3" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">image1.png </span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">image2.gif</span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">image3</span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">image4    </span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;"> image5.svg</span></div><div class="gallerytext"> <a rel="mw:ExtLink" href="http://///////">http://///////</a></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">* image6</span></div><div class="gallerytext"></div></li>
+</ul>
 !! end
 
 !! test
-Gallery (with options)
+Gallery (with options, html)
+!! options
+parsoid={
+  "modes": ["wt2html", "html2html"],
+  "nativeGallery": true
+}
 !! wikitext
-<gallery widths='70px' heights='40px' perrow='2' caption='Foo [[Main Page]]' >
+<gallery widths="70px" heights="40px" perrow="2" caption="Foo [[Main Page]]">
 File:Nonexistent.jpg|caption
 File:Nonexistent.jpg
 image:foobar.jpg|some '''caption''' [[Main Page]]
 image:foobar.jpg
 image:foobar.jpg|Blabla|alt=This is a foo-bar.|blabla.
 </gallery>
-!! html
+!! html/php
 <ul class="gallery mw-gallery-traditional" style="max-width: 226px;_width: 226px;">
        <li class='gallerycaption'>Foo <a href="/wiki/Main_Page" title="Main Page">Main Page</a></li>
                <li class="gallerybox" style="width: 105px"><div style="width: 105px">
@@ -18957,17 +19050,92 @@ image:foobar.jpg|Blabla|alt=This is a foo-bar.|blabla.
                </div></li>
 </ul>
 
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" style="max-width: 226px; _width: 226px;" typeof="mw:Extension/gallery" about="#mwt3" data-mw='{"name":"gallery","attrs":{"widths":"70px","heights":"40px","perrow":"2"},"body":{}}'>
+<li class="gallerycaption">Foo <a rel="mw:WikiLink" href="./Main_Page" title="Main Page">Main Page</a></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">File:Nonexistent.jpg</span></div><div class="gallerytext">caption</div></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">File:Nonexistent.jpg</span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="8" width="70"/></a></span></div><div class="gallerytext">some <b>caption</b> <a rel="mw:WikiLink" href="./Main_Page" title="Main Page">Main Page</a></div></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="8" width="70"/></a></span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img alt="This is a foo-bar." resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="8" width="70"/></a></span></div><div class="gallerytext">blabla.</div></li>
+</ul>
+!! end
+
+!! test
+Gallery (with options, extsrc)
+!! options
+parsoid={
+  "nativeGallery": false
+}
+!! wikitext
+<gallery widths="70px" heights="40px" perrow="2" caption="Foo [[Main Page]]">
+File:Nonexistent.jpg|caption
+File:Nonexistent.jpg
+image:foobar.jpg|some '''caption''' [[Main Page]]
+image:foobar.jpg
+image:foobar.jpg|Blabla|alt=This is a foo-bar.|blabla.
+</gallery>
+!! html/php
+<ul class="gallery mw-gallery-traditional" style="max-width: 226px;_width: 226px;">
+       <li class='gallerycaption'>Foo <a href="/wiki/Main_Page" title="Main Page">Main Page</a></li>
+               <li class="gallerybox" style="width: 105px"><div style="width: 105px">
+                       <div class="thumb" style="height: 70px;">Nonexistent.jpg</div>
+                       <div class="gallerytext">
+<p>caption
+</p>
+                       </div>
+               </div></li>
+               <li class="gallerybox" style="width: 105px"><div style="width: 105px">
+                       <div class="thumb" style="height: 70px;">Nonexistent.jpg</div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+               <li class="gallerybox" style="width: 105px"><div style="width: 105px">
+                       <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/105px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/140px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>some <b>caption</b> <a href="/wiki/Main_Page" title="Main Page">Main Page</a>
+</p>
+                       </div>
+               </div></li>
+               <li class="gallerybox" style="width: 105px"><div style="width: 105px">
+                       <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/105px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/140px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+               <li class="gallerybox" style="width: 105px"><div style="width: 105px">
+                       <div class="thumb" style="width: 100px;"><div style="margin:31px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="This is a foo-bar." src="http://example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" width="70" height="8" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/105px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/140px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>blabla.
+</p>
+                       </div>
+               </div></li>
+</ul>
+
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" style="max-width: 226px; _width: 226px;" typeof="mw:Extension/gallery" about="#mwt3" data-parsoid='{}' data-mw='{"name":"gallery","attrs":{"widths":"70px","heights":"40px","perrow":"2","caption":"Foo [[Main Page]]"},"body":{"extsrc":"\nFile:Nonexistent.jpg|caption\nFile:Nonexistent.jpg\nimage:foobar.jpg|some &#39;&#39;&#39;caption&#39;&#39;&#39; [[Main Page]]\nimage:foobar.jpg\nimage:foobar.jpg|Blabla|alt=This is a foo-bar.|blabla.\n"}}'>
+<li class="gallerycaption">Foo <a rel="mw:WikiLink" href="./Main_Page" title="Main Page">Main Page</a></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">File:Nonexistent.jpg</span></div><div class="gallerytext">caption</div></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">File:Nonexistent.jpg</span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="8" width="70"/></a></span></div><div class="gallerytext">some <b>caption</b> <a rel="mw:WikiLink" href="./Main_Page" title="Main Page">Main Page</a></div></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="8" width="70"/></a></span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 105px;"><div class="thumb" style="width: 100px; height: 70px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img alt="This is a foo-bar." resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/70px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="8" width="70"/></a></span></div><div class="gallerytext">blabla.</div></li>
+</ul>
 !! end
 
 !! test
 Gallery with link that has fragment
+!! options
+parsoid={
+  "modes": ["wt2html", "html2html"],
+  "nativeGallery": true
+}
 !! wikitext
 <gallery>
 image:foobar.jpg|link=Main_Page
 image:foobar.jpg|link=Main_Page#section
 image:foobar.jpg|link=Main Page#section|caption
 </gallery>
-!! html
+!! html/php
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/Main_Page"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
@@ -18988,16 +19156,56 @@ image:foobar.jpg|link=Main Page#section|caption
                </div></li>
 </ul>
 
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt2" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./Main_Page"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./Main_Page#section"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./Main_Page#section"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext">caption</div></li>
+</ul>
+!! end
+
+## Whoops, Parsoid shouldn't be parsing templates in the attribute caption!
+!! test
+Gallery with template inside caption
+!! options
+parsoid={
+  "nativeGallery": true
+}
+!! wikitext
+<gallery caption="{{echo|hi}}">
+File:Foobar.jpg|{{echo|ho}}
+</gallery>
+!! html/php
+<ul class="gallery mw-gallery-traditional">
+       <li class='gallerycaption'>{{echo|hi}}</li>
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>ho
+</p>
+                       </div>
+               </div></li>
+</ul>
+
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt6" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerycaption"><span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"hi"}},"i":0}}]}'>hi</span></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"><span about="#mwt5" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"ho"}},"i":0}}]}'>ho</span></div></li>
+</ul>
 !! end
 
 !! test
 Gallery with wikitext inside caption
+!! options
+parsoid={
+  "nativeGallery": true
+}
 !! wikitext
 <gallery>
-File:foobar.jpg|[[File:foobar.jpg|20px|desc|alt=inneralt]]|alt=galleryalt
-File:foobar.jpg|{{Test|unamedParam|alt=param}}|alt=galleryalt
+File:Foobar.jpg|alt=galleryalt|[[File:Foobar.jpg|alt=inneralt|20x20px|desc]]
+File:Foobar.jpg|alt=galleryalt|{{Test|unamedParam|alt=param}}
 </gallery>
-!! html
+!! html/php
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
@@ -19015,18 +19223,27 @@ File:foobar.jpg|{{Test|unamedParam|alt=param}}|alt=galleryalt
                </div></li>
 </ul>
 
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt6" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img alt="galleryalt" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"><span typeof="mw:Image" data-mw='{"caption":"desc"}'><a href="./File:Foobar.jpg"><img alt="inneralt" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="2" width="20"/></a></span></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img alt="galleryalt" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"><span about="#mwt4" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"Test","href":"./Template:Test"},"params":{"1":{"wt":"unamedParam"},"alt":{"wt":"param"}},"i":0}}]}'>This is a test template</span></div></li>
+</ul>
 !! end
 
 !! test
-gallery (with showfilename option)
+Gallery (with showfilename option)
+!! options
+parsoid={
+  "nativeGallery": true
+}
 !! wikitext
-<gallery showfilename>
+<gallery showfilename="">
 File:Nonexistent.jpg|caption
 File:Nonexistent.jpg
-image:foobar.jpg|some '''caption''' [[Main Page]]
+File:Foobar.jpg|some '''caption''' [[Main Page]]
 File:Foobar.jpg
 </gallery>
-!! html
+!! html/php
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="height: 150px;">Nonexistent.jpg</div>
@@ -19060,10 +19277,23 @@ some <b>caption</b> <a href="/wiki/Main_Page" title="Main Page">Main Page</a>
                </div></li>
 </ul>
 
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt3" data-mw='{"name":"gallery","attrs":{"showfilename":""},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">File:Nonexistent.jpg</span></div><div class="gallerytext"><a href="./File:Nonexistent.jpg" class="galleryfilename galleryfilename-truncate" title="File:Nonexistent.jpg">File:Nonexistent.jpg</a>caption</div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">File:Nonexistent.jpg</span></div><div class="gallerytext"><a href="./File:Nonexistent.jpg" class="galleryfilename galleryfilename-truncate" title="File:Nonexistent.jpg">File:Nonexistent.jpg</a></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"><a href="./File:Foobar.jpg" class="galleryfilename galleryfilename-truncate" title="File:Foobar.jpg">File:Foobar.jpg</a>some <b>caption</b> <a rel="mw:WikiLink" href="./Main_Page" title="Main Page">Main Page</a></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"><a href="./File:Foobar.jpg" class="galleryfilename galleryfilename-truncate" title="File:Foobar.jpg">File:Foobar.jpg</a></div></li>
+</ul>
 !! end
 
+## Should Parsoid be preserving these variations?
 !! test
 Gallery (with namespace-less filenames)
+!! options
+parsoid={
+  "modes": ["wt2html", "html2html"],
+  "nativeGallery": true
+}
 !! wikitext
 <gallery>
 File:Nonexistent.jpg
@@ -19071,7 +19301,7 @@ Nonexistent.jpg
 image:foobar.jpg
 foobar.jpg
 </gallery>
-!! html
+!! html/php
 <ul class="gallery mw-gallery-traditional">
                <li class="gallerybox" style="width: 155px"><div style="width: 155px">
                        <div class="thumb" style="height: 150px;">Nonexistent.jpg</div>
@@ -19095,6 +19325,115 @@ foobar.jpg
                </div></li>
 </ul>
 
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt2" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">File:Nonexistent.jpg</span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span style="vertical-align: middle; display: inline-block;">Nonexistent.jpg</span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"></div></li>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"></div></li>
+</ul>
+!! end
+
+!! test
+Gallery override link with WikiLink (T36852)
+!! options
+parsoid={
+  "nativeGallery": true
+}
+!! wikitext
+<gallery>
+File:Foobar.jpg|alt=galleryalt|link=InterWikiLink
+</gallery>
+!! html/php
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/InterWikiLink"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+</ul>
+
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt2" data-parsoid='{"dsr":[0,70,2,2]}' data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./InterWikiLink"><img alt="galleryalt" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"></div></li>
+</ul>
+!! end
+
+!! test
+Gallery override link with absolute external link (T36852)
+!! options
+parsoid={
+  "nativeGallery": true
+}
+!! wikitext
+<gallery>
+File:Foobar.jpg|alt=galleryalt|link=http://www.example.org
+</gallery>
+!! html/php
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="http://www.example.org"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+</ul>
+
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt2" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="http://www.example.org"><img alt="galleryalt" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"></div></li>
+</ul>
+!! end
+
+!! test
+Gallery override link with malicious javascript (T36852)
+!! options
+parsoid={
+  "modes": ["wt2html", "html2html"],
+  "nativeGallery": true
+}
+!! wikitext
+<gallery>
+File:Foobar.jpg|alt=galleryalt|link=" onclick="alert('malicious javascript code!');
+</gallery>
+!! html/php
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/%22_onclick%3D%22alert(%27malicious_javascript_code!%27);"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+</ul>
+
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt2" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./&quot;_onclick=&quot;alert('malicious_javascript_code!');"><img alt="galleryalt" resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext"></div></li>
+</ul>
+!! end
+
+!! test
+Gallery with invalid title as link (T45964)
+!! options
+parsoid={
+  "modes": ["wt2html", "html2html"],
+  "nativeGallery": true
+}
+!! wikitext
+<gallery>
+File:Foobar.jpg|link=<
+</gallery>
+!! html/php
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="Foobar.jpg" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+                       </div>
+               </div></li>
+</ul>
+
+!! html/parsoid
+<ul class="gallery mw-gallery-traditional" typeof="mw:Extension/gallery" about="#mwt2" data-mw='{"name":"gallery","attrs":{},"body":{}}'>
+<li class="gallerybox" style="width: 155px;"><div class="thumb" style="width: 150px; height: 150px;"><span style="display: inline-block; height: 100%; vertical-align: middle;"></span><span typeof="mw:Image" style="vertical-align: middle; display: inline-block;"><a href="./File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="14" width="120"/></a></span></div><div class="gallerytext">link=&lt;</div></li>
+</ul>
 !! end
 
 !! test
@@ -20294,16 +20633,70 @@ language=sr variant=sr-ec
 </p>
 !! end
 
-# FIXME: This test is currently broken in the PHP parser (bug 52661)
 !! test
-Don't break image parsing if language converter markup is in the caption.
+T146304: Don't break template parsing if language converter markup is in the parameter.
+!! options
+language=sr variant=sr-ec
+!! wikitext
+{{echo|-{R|foo}-}}
+!! html/php
+<p>foo
+</p>
+!! end
+
+!! test
+T146305: Don't break image parsing if language converter markup is in the caption.
 !! options
 language=sr
 !! wikitext
-[[File:Foobar.jpg|-{R|caption}-]]
+[[File:Foobar.jpg|thumb|-{R|caption:}-]]
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/%D0%94%D0%B0%D1%82%D0%BE%D1%82%D0%B5%D0%BA%D0%B0:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/%D0%94%D0%B0%D1%82%D0%BE%D1%82%D0%B5%D0%BA%D0%B0:Foobar.jpg" class="internal" title="Повећај"></a></div>caption:</div></div></div>
+
 !! html/parsoid
-<p><a href="/wiki/File:Foobar.jpg" class="image" title="caption"><img alt="caption" src="http://example.com/images/3/3a/Foobar.jpg" width="1941" height="220" /></a>
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="./Датотека:Foobar.jpg"><img resource="./Датотека:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><span typeof="mw:LanguageVariant" data-mw='{"disabled":true,"show":true,"text":"caption:"}'></span></figcaption></figure>
+!! end
+
+!! test
+T146305: Don't break image parsing if nested language converter markup is in the caption.
+!! options
+language=zh variant=zh-cn
+!! wikitext
+[[File:Foobar.jpg|thumb|-{zh-cn:blog (hk: -{zh-hans|WEBJOURNAL}-, tw: -{zh-hans|WEBLOG}-)}-]]
+!! html/php
+<div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="" src="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg" width="180" height="20" class="thumbimage" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/270px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/360px-Foobar.jpg 2x" /></a>  <div class="thumbcaption"><div class="magnify"><a href="/wiki/File:Foobar.jpg" class="internal" title="放大"></a></div>blog (hk: WEBJOURNAL, tw: WEBLOG)</div></div></div>
+
+!! html/parsoid
+<figure class="mw-default-size" typeof="mw:Image/Thumb"><a href="File:Foobar.jpg"><img resource="./File:Foobar.jpg" src="//example.com/images/thumb/3/3a/Foobar.jpg/220px-Foobar.jpg" data-file-width="1941" data-file-height="220" data-file-type="bitmap" height="25" width="220"/></a><figcaption><span typeof="mw:LanguageVariant" data-mw='{"bidir":[{"l":"zh-cn","t":"blog (hk: &lt;span typeof=\"mw:LanguageVariant\" data-parsoid=&#39;{\"fl\":[\"zh-hans\"],\"dsr\":[42,64,null,2]}&#39; data-mw=&#39;{\"filter\":[\"zh-hans\"],\"text\":\"WEBJOURNAL\"}&#39;>&lt;/span>, tw: &lt;span typeof=\"mw:LanguageVariant\" data-parsoid=&#39;{\"fl\":[\"zh-hans\"],\"dsr\":[70,88,null,2]}&#39; data-mw=&#39;{\"filter\":[\"zh-hans\"],\"text\":\"WEBLOG\"}&#39;>&lt;/span>)"}],"show":true}'></span></figcaption></figure>
+!! end
+
+!! test
+Don't break gallery if language converter markup is inside.
+!! options
+language=zh
+!! wikitext
+<gallery>
+File:foobar.jpg|[[File:foobar.jpg|20px|desc|alt=-{R|foo}-|-{R|bar}-]]|alt=-{R|bat}-
+File:foobar.jpg|{{Test|unamedParam|alt=-{R|param}-}}|alt=galleryalt
+</gallery>
+!! html
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="bat" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p><a href="/wiki/File:Foobar.jpg" class="image" title="bar"><img alt="foo" src="http://example.com/images/thumb/3/3a/Foobar.jpg/20px-Foobar.jpg" width="20" height="2" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/30px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/40px-Foobar.jpg 2x" /></a>
 </p>
+                       </div>
+               </div></li>
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/File:Foobar.jpg" class="image"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>This is a test template
+</p>
+                       </div>
+               </div></li>
+</ul>
+
 !! end
 
 # FIXME: This test is currently broken in the PHP parser (bug 52661)
@@ -20321,9 +20714,8 @@ language=zh variant=zh-cn
 </dt></dl>
 !! end
 
-# FIXME: This test is currently broken in the PHP parser (bug 52661)
 !! test
-Don't break table handling if language converter markup is in the cell.
+T153140: Don't break table handling if language converter markup is in the cell.
 !! options
 language=sr variant=sr-ec
 !! wikitext
@@ -20335,7 +20727,7 @@ language=sr variant=sr-ec
 <table>
 
 <tr>
-<td>Б}-
+<td> B
 </td></tr></table>
 
 !! html/parsoid
@@ -20954,7 +21346,7 @@ Edit comment with link with more than one pipe (T99346)
 comment
 !! wikitext
 [[Main Page|Many|pipes]]
-!! html
+!! html/php
 <a href="/wiki/Main_Page" title="Main Page">Many|pipes</a>
 !! end
 
@@ -20964,7 +21356,7 @@ Complex edit comment with link with more than one pipe (T99346)
 comment
 !! wikitext
 Created page with "<noinclude>[[Category:Requests for permissions/Bot|{{subst:#titleparts:{{subst:PAGENAME}}|1|3}}]]</noinclude> === [[User:MineoBot|]] 8=== {{Request for permissions/links|Mineo..."
-!! html
+!! html/php
 Created page with &quot;&lt;noinclude&gt;<a href="/index.php?title=Category:Requests_for_permissions/Bot&amp;action=edit&amp;redlink=1" class="new" title="Category:Requests for permissions/Bot (page does not exist)">{{subst:#titleparts:{{subst:PAGENAME}}|1|3}}</a>&lt;/noinclude&gt; === <a href="/index.php?title=User:MineoBot&amp;action=edit&amp;redlink=1" class="new" title="User:MineoBot (page does not exist)">User:MineoBot</a> 8=== {{Request for permissions/links|Mineo...&quot;
 !! end
 
@@ -21765,7 +22157,7 @@ Strip marker in urlencode
 {{urlencode:x<nowiki/>y|wiki}}
 {{urlencode:x<nowiki/>y|path}}
 {{urlencode:x<pre id="one">two</pre>y}}
-!! html
+!! html/php
 <p>xy
 xy
 xy
@@ -21941,6 +22333,27 @@ File:foobar.jpg|caption|alt=galleryalt|link=http://www.example.org
 
 !! end
 
+!! test
+Gallery override link with absolute external link with LanguageConverter
+!! options
+language=zh
+!! input
+<gallery>
+File:foobar.jpg|caption|alt=galleryalt|link=http://www.example.org
+</gallery>
+!! result
+<ul class="gallery mw-gallery-traditional">
+               <li class="gallerybox" style="width: 155px"><div style="width: 155px">
+                       <div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="http://www.example.org"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
+                       <div class="gallerytext">
+<p>caption
+</p>
+                       </div>
+               </div></li>
+</ul>
+
+!! end
+
 !!test
 Gallery override link with malicious javascript (bug 34852)
 !! wikitext
@@ -22173,13 +22586,13 @@ B <ref name="x">foo</ref>
 C <ref name="y" />
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-x_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-2"},"attrs":{"name":"x"}}'><a href="#cite_note-x-2"><span class="mw-reflink-text">[2]</span></a></span>
-C <span about="#mwt6" class="mw-ref" id="cite_ref-y_3-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"y"}}'><a href="#cite_note-y-3"><span class="mw-reflink-text">[3]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
+B <span about="#mwt4" class="mw-ref" id="cite_ref-x_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-2"},"attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-2"><span class="mw-reflink-text">[2]</span></a></span>
+C <span about="#mwt6" class="mw-ref" id="cite_ref-y_3-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"y"}}'><a href="./Main_Page#cite_note-y-3"><span class="mw-reflink-text">[3]</span></a></span></p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-x-2" id="cite_note-x-2"><a href="#cite_ref-x_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-x-2" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-y-3" id="cite_note-y-3"><a href="#cite_ref-y_3-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-y-3" class="mw-reference-text"></span></li>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-x-2" id="cite_note-x-2"><a href="./Main_Page#cite_ref-x_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-x-2" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-y-3" id="cite_note-y-3"><a href="./Main_Page#cite_ref-y_3-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-y-3" class="mw-reference-text"></span></li>
 </ol>
 !!end
 
@@ -22190,10 +22603,10 @@ A <ref name="x">foo</ref>
 B <ref name="x" />
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
+B <span about="#mwt4" class="mw-ref" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy"><a href="#cite_ref-x_1-0"><span class="mw-linkback-text">1 </span></a><a href="#cite_ref-x_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-x_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-x_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
 </ol>
 !!end
 
@@ -22205,11 +22618,11 @@ B <ref name=" x " />
 C <ref name= x  />
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
-C <span about="#mwt6" class="mw-ref" id="cite_ref-x_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-x_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-x-1"},"attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
+B <span about="#mwt4" class="mw-ref" id="cite_ref-x_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span>
+C <span about="#mwt6" class="mw-ref" id="cite_ref-x_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"x"}}'><a href="./Main_Page#cite_note-x-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy"><a href="#cite_ref-x_1-0"><span class="mw-linkback-text">1 </span></a><a href="#cite_ref-x_1-1"><span class="mw-linkback-text">2 </span></a><a href="#cite_ref-x_1-2"><span class="mw-linkback-text">3 </span></a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-x-1" id="cite_note-x-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-x_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-x_1-1"><span class="mw-linkback-text">2 </span></a><a href="./Main_Page#cite_ref-x_1-2"><span class="mw-linkback-text">3 </span></a></span> <span id="mw-reference-text-cite_note-x-1" class="mw-reference-text">foo</span></li>
 </ol>
 !!end
 
@@ -22220,9 +22633,9 @@ Ref: 4. 'constructor' should be accepted as a valid ref-name
 A <ref name="constructor">foo</ref>
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-constructor_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-constructor-1"},"attrs":{"name":"constructor"}}'><a href="#cite_note-constructor-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-constructor_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-constructor-1"},"attrs":{"name":"constructor"}}'><a href="./Main_Page#cite_note-constructor-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-constructor-1" id="cite_note-constructor-1"><a href="#cite_ref-constructor_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-constructor-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-constructor-1" id="cite_note-constructor-1"><a href="./Main_Page#cite_ref-constructor_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-constructor-1" class="mw-reference-text">foo</span></li>
 </ol>
 !!end
 
@@ -22235,10 +22648,10 @@ A <ref>
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">This is a <b><a rel="mw:WikiLink" href="Bolded_link" title="Bolded link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">This is a <b><a rel="mw:WikiLink" href="Bolded_link" title="Bolded link">bolded link</a></b> and this is a <span about="#mwt3" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"transclusion"}},"i":0}}]}'>transclusion</span>
 </span></li>
 </ol>
 !!end
@@ -22254,10 +22667,10 @@ A <ref>
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
  bar
  baz
 </span></li>
@@ -22282,10 +22695,10 @@ booz
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo
 
 bar
 
@@ -22306,9 +22719,9 @@ A <ref> foo {{echo|</ref> B C}}
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C}}</p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C}}</p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo {{echo|</span></li>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo {{echo|</span></li>
 </ol>
 !!end
 
@@ -22318,9 +22731,9 @@ Ref: 9. unclosed comments should not leak out of ref-body
 A <ref> foo <!--</ref> B C
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C</p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C</p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <!----></span></li>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <!----></span></li>
 </ol>
 !!end
 
@@ -22331,11 +22744,11 @@ A <ref> <b> foo </ref> B C
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C</p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B C</p>
 
 
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"><b data-parsoid='{"stx":"html","autoInsertedEnd":true}'> foo </b></span></li>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"><b data-parsoid='{"stx":"html","autoInsertedEnd":true}'> foo </b></span></li>
 </ol>
 !!end
 
@@ -22346,11 +22759,11 @@ A <ref>foo</ref> B
 C <ref>bar</ref> D
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B
-C <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span> D</p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B
+C <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span> D</p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-2" id="cite_note-2"><a href="#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
 </ol>
 !!end
 
 <!--the newline at the end of this line moves out of the p tag--><p>a</p>
 
 
-<p>b<!--the newline at the end of this line stays inside the p tag--> <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-<span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span></p>
+<p>b<!--the newline at the end of this line stays inside the p tag--> <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
+<span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span></p>
 
 <p>c</p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"></span></li>
-<li about="#cite_note-2" id="cite_note-2"><a href="#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text"></span></li></ol>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"></span></li>
+<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text"></span></li></ol>
 !!end
 
 !!test
@@ -22385,28 +22798,29 @@ Ref: 13. ref-tags are not SOL-transparent and block indent-pres
 </ref> B
 <references />
 !! html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> A
-<span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span> B</p>
+<p><span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> A
+<span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[2]</span></a></span> B</p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
-<li about="#cite_note-2" id="cite_note-2"><a href="#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar
 </span></li>
 </ol>
 !!end
 
-!!test
+## Roundtripping fails because of nowiki'ing
+!! test
 Ref: 14. A nested ref-tag should be emitted as plain text
+!! options
+parsoid=wt2html
 !! wikitext
 <ref>foo <ref>bar</ref> baz</ref>
 
 <references />
 !! html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-</p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo &lt;ref>bar&lt;/ref> baz</span></li>
-</ol>
-!!end
+<p><span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span> baz&lt;/ref></p>
+
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">foo &lt;ref>bar</span></li></ol>
+!! end
 
 !!test
 Ref: 15. ref-tags with identical names should get identical indexes
@@ -22416,10 +22830,10 @@ B1 <ref name="b" /> B2 <ref name="b">bar</ref>
 
 <references />
 !! html/parsoid
-<p>A1 <span about="#mwt3" class="mw-ref" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a-1"},"attrs":{"name":"a"}}'><a href="#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span> A2 <span about="#mwt4" class="mw-ref" id="cite_ref-a_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span>
-B1 <span about="#mwt7" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"b"}}'><a href="#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span> B2 <span about="#mwt8" class="mw-ref" id="cite_ref-b_2-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span></p>
+<p>A1 <span about="#mwt3" class="mw-ref" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a-1"},"attrs":{"name":"a"}}'><a href="./Main_Page#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span> A2 <span about="#mwt4" class="mw-ref" id="cite_ref-a_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="./Main_Page#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span>
+B1 <span about="#mwt7" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"b"}}'><a href="./Main_Page#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span> B2 <span about="#mwt8" class="mw-ref" id="cite_ref-b_2-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="./Main_Page#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span></p>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy"><a href="#cite_ref-a_1-0"><span class="mw-linkback-text">1 </span></a><a href="#cite_ref-a_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy"><a href="#cite_ref-b_2-0"><span class="mw-linkback-text">1 </span></a><a href="#cite_ref-b_2-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-a-1" id="cite_note-a-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-a_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-a_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-b_2-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-b_2-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
 </ol>
 !!end
 
@@ -22433,24 +22847,24 @@ A <ref >foo</ref >
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
 !!end
 
 !!test
 Ref: 17. Generate valid HTML5 id/about attributes
 !!wikitext
 <ref name="a b">foo</ref>
+<ref name=":0">ve-created name</ref>
 
 <references />
 !!html/parsoid
-<p><span class="mw-ref" id="cite_ref-a_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_b-1"},"attrs":{"name":"a b"}}'><a href="#cite_note-a_b-1"><span class="mw-reflink-text">[1]</span></a></span>
-</p>
+<p><span about="#mwt2" class="mw-ref" id="cite_ref-a_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_b-1"},"attrs":{"name":"a b"}}'><a href="./Main_Page#cite_note-a_b-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span>
+<span about="#mwt4" class="mw-ref" id="cite_ref-:0_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-:0-2"},"attrs":{"name":":0"}}'><a href="./Main_Page#cite_note-:0-2" style="counter-reset: mw-Ref 2;"><span class="mw-reflink-text">[2]</span></a></span>
+
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-a_b-1" id="cite_note-a_b-1"><a href="./Main_Page#cite_ref-a_b_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-a_b-1" class="mw-reference-text">foo</span></li><li about="#cite_note-:0-2" id="cite_note-:0-2"><a href="./Main_Page#cite_ref-:0_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-:0-2" class="mw-reference-text">ve-created name</span></li></ol>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-a_b-1" id="cite_note-a_b-1"><a href="#cite_ref-a_b_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-a_b-1" class="mw-reference-text">foo</span></li>
-</ol>
 !!end
 
 !!test
@@ -22460,11 +22874,11 @@ Ref: 18. T58916: Extension attributes should be parsed as plain text
 
 <references />
 !!html/parsoid
-<p><span class="mw-ref" id="cite_ref-.7B.7Becho.7Ca.7D.7D_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1"},"attrs":{"name":"{{echo|a}}"}}'><a href="#cite_note-.7B.7Becho.7Ca.7D.7D-1"><span class="mw-reflink-text">[1]</span></a></span>
+<p><span class="mw-ref" id="cite_ref-.7B.7Becho.7Ca.7D.7D_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1"},"attrs":{"name":"{{echo|a}}"}}'><a href="./Main_Page#cite_note-.7B.7Becho.7Ca.7D.7D-1"><span class="mw-reflink-text">[1]</span></a></span>
 </p>
 
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-.7B.7Becho.7Ca.7D.7D-1" id="cite_note-.7B.7Becho.7Ca.7D.7D-1"><a href="#cite_ref-.7B.7Becho.7Ca.7D.7D_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-.7B.7Becho.7Ca.7D.7D-1" id="cite_note-.7B.7Becho.7Ca.7D.7D-1"><a href="./Main_Page#cite_ref-.7B.7Becho.7Ca.7D.7D_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-.7B.7Becho.7Ca.7D.7D-1" class="mw-reference-text">foo</span></li>
 </ol>
 !!end
 
@@ -22475,10 +22889,10 @@ Ref: 19. ref-tags with identical name encodings should get identical indexes
 
 <references />
 !! html/parsoid
-<p>1 <span about="#mwt3" class="mw-ref" id="cite_ref-a_.26_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_.26_b-1"},"attrs":{"name":"a &amp; b"}}'><a href="#cite_note-a_.26_b-1"><span class="mw-reflink-text">[1]</span></a></span> 2 <span about="#mwt4" class="mw-ref" id="cite_ref-a_.26_b_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a &amp;amp; b"}}'><a href="#cite_note-a_.26_b-1"><span class="mw-reflink-text">[1]</span></a></span>
+<p>1 <span about="#mwt3" class="mw-ref" id="cite_ref-a_.26_b_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-a_.26_b-1"},"attrs":{"name":"a &amp; b"}}'><a href="./Main_Page#cite_note-a_.26_b-1"><span class="mw-reflink-text">[1]</span></a></span> 2 <span about="#mwt4" class="mw-ref" id="cite_ref-a_.26_b_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a &amp;amp; b"}}'><a href="./Main_Page#cite_note-a_.26_b-1"><span class="mw-reflink-text">[1]</span></a></span>
 </p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-a_.26_b-1" id="cite_note-a_.26_b-1"><span rel="mw:referencedBy"><a href="#cite_ref-a_.26_b_1-0"><span class="mw-linkback-text">1 </span></a><a href="#cite_ref-a_.26_b_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-a_.26_b-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-a_.26_b-1" id="cite_note-a_.26_b-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-a_.26_b_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-a_.26_b_1-1"><span class="mw-linkback-text">2 </span></a></span> <span id="mw-reference-text-cite_note-a_.26_b-1" class="mw-reference-text">foo</span></li>
 </ol>
 !!end
 
@@ -22491,11 +22905,11 @@ C <ref name="foo" />
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-foo_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-foo-1"},"attrs":{"name":"foo"}}'><a href="#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-foo_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"html":"Foo two"},"attrs":{"name":"foo"}}'><a href="#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span>
-C <span about="#mwt6" class="mw-ref" id="cite_ref-foo_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"foo"}}'><a href="#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-foo_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-foo-1"},"attrs":{"name":"foo"}}'><a href="./Main_Page#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span>
+B <span about="#mwt4" class="mw-ref" id="cite_ref-foo_1-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"html":"Foo two"},"attrs":{"name":"foo"}}'><a href="./Main_Page#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span>
+C <span about="#mwt6" class="mw-ref" id="cite_ref-foo_1-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"foo"}}'><a href="./Main_Page#cite_note-foo-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-foo-1" id="cite_note-foo-1"><span rel="mw:referencedBy"><a href="#cite_ref-foo_1-0"><span class="mw-linkback-text">1 </span></a><a href="#cite_ref-foo_1-1"><span class="mw-linkback-text">2 </span></a><a href="#cite_ref-foo_1-2"><span class="mw-linkback-text">3 </span></a></span> <span id="mw-reference-text-cite_note-foo-1" class="mw-reference-text">Foo one</span></li>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-foo-1" id="cite_note-foo-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-foo_1-0"><span class="mw-linkback-text">1 </span></a><a href="./Main_Page#cite_ref-foo_1-1"><span class="mw-linkback-text">2 </span></a><a href="./Main_Page#cite_ref-foo_1-2"><span class="mw-linkback-text">3 </span></a></span> <span id="mw-reference-text-cite_note-foo-1" class="mw-reference-text">Foo one</span></li>
 </ol>
 !!end
 
@@ -22518,18 +22932,18 @@ C <ref>baz</ref>
 <references />
 <references group="b" />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="#cite_note-1" data-mw-group="a"><span class="mw-reflink-text">[a 1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"b"}}'><a href="#cite_note-2" data-mw-group="b"><span class="mw-reflink-text">[b 1]</span></a></span>
-C <span class="mw-ref" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="#cite_note-3"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="./Main_Page#cite_note-1" data-mw-group="a"><span class="mw-reflink-text">[a 1]</span></a></span>
+B <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"b"}}'><a href="./Main_Page#cite_note-2" data-mw-group="b"><span class="mw-reflink-text">[b 1]</span></a></span>
+C <span class="mw-ref" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="./Main_Page#cite_note-3"><span class="mw-reflink-text">[1]</span></a></span></p>
 
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw-group="a" data-mw='{"name":"references","attrs":{"group":"a"}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" data-mw-group="a" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" data-mw-group="a" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
 </ol>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-3" id="cite_note-3"><a href="#cite_ref-3" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">baz</span></li>
+<li about="#cite_note-3" id="cite_note-3"><a href="./Main_Page#cite_ref-3" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">baz</span></li>
 </ol>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt12" data-mw-group="b" data-mw='{"name":"references","attrs":{"group":"b"}}'>
-<li about="#cite_note-2" id="cite_note-2"><a href="#cite_ref-2" data-mw-group="b" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
+<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" data-mw-group="b" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
 </ol>
 !!end
 
@@ -22544,15 +22958,15 @@ B <ref>bar</ref>
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
 </ol>
 
-<p>B <span about="#mwt6" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="#cite_note-2"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>B <span about="#mwt6" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[1]</span></a></span></p>
 
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-2" id="cite_note-2"><a href="#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
+<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
 </ol>
 !!end
 
@@ -22568,15 +22982,15 @@ C <ref>cfoo</ref>
 
 <references />
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="#cite_note-1" data-mw-group="a"><span class="mw-reflink-text">[a 1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="#cite_note-2"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{"group":"a"}}'><a href="./Main_Page#cite_note-1" data-mw-group="a"><span class="mw-reflink-text">[a 1]</span></a></span>
+B <span about="#mwt4" class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{}}'><a href="./Main_Page#cite_note-2"><span class="mw-reflink-text">[1]</span></a></span></p>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw-group="a" data-mw='{"name":"references","attrs":{"group":"a"}}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" data-mw-group="a" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">afoo</span></li>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw-group="a" data-mw='{"name":"references","attrs":{"group":"a"}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" data-mw-group="a" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">afoo</span></li>
 </ol>
 
-<p>C <span about="#mwt8" class="mw-ref" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="#cite_note-3"><span class="mw-reflink-text">[2]</span></a></span></p>
+<p>C <span about="#mwt8" class="mw-ref" id="cite_ref-3" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-3"},"attrs":{}}'><a href="./Main_Page#cite_note-3"><span class="mw-reflink-text">[2]</span></a></span></p>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-2" id="cite_note-2"><a href="#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bfoo</span></li><li about="#cite_note-3" id="cite_note-3"><a href="#cite_ref-3" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">cfoo</span></li>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt10" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bfoo</span></li><li about="#cite_note-3" id="cite_note-3"><a href="./Main_Page#cite_ref-3" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-3" class="mw-reference-text">cfoo</span></li>
 </ol>
 !!end
 
@@ -22594,11 +23008,11 @@ B <ref name="b">bar</ref>
 This should just get lost.
 </references>
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span></p>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-a_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"name":"a"}}'><a href="./Main_Page#cite_note-a-1"><span class="mw-reflink-text">[1]</span></a></span>
+B <span about="#mwt4" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-b-2"},"attrs":{"name":"b"}}'><a href="./Main_Page#cite_note-b-2"><span class="mw-reflink-text">[2]</span></a></span></p>
 
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{},"body":{"html":"\n&lt;span about=\"#mwt8\" class=\"mw-ref\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[59,82,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-a-1\"},\"attrs\":{\"name\":\"a\"}}&#39;>&lt;a href=\"#cite_note-a-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]&lt;/span>&lt;/a>&lt;/span>\n"}}'><li about="#cite_note-a-1" id="cite_note-a-1"><a href="#cite_ref-a_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><a href="#cite_ref-b_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{},"body":{"html":"\n&lt;span about=\"#mwt8\" class=\"mw-ref\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[59,82,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-a-1\"},\"attrs\":{\"name\":\"a\"}}&#39;>&lt;a href=\"./Main_Page#cite_note-a-1\" style=\"counter-reset: mw-Ref 1;\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[1]&lt;/span>&lt;/a>&lt;/span>\n"}}'><li about="#cite_note-a-1" id="cite_note-a-1"><a href="./Main_Page#cite_ref-a_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-a-1" class="mw-reference-text">foo</span></li><li about="#cite_note-b-2" id="cite_note-b-2"><a href="./Main_Page#cite_ref-b_2-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">bar</span></li>
 </ol>
 !! end
 
@@ -22607,7 +23021,7 @@ References: 6. <references /> from a transclusion
 !! wikitext
 <ref>Foo</ref> {{echo|<references />}}
 !! html/parsoid
-<p><span about="#mwt3" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p> <ol class="mw-references" typeof="mw:Extension/references mw:Transclusion" about="#mwt4" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;references />"}},"i":0}}]}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">Foo</span></li>
+<p><span about="#mwt3" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p> <ol class="mw-references" typeof="mw:Extension/references mw:Transclusion" about="#mwt4" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;references />"}},"i":0}}]}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">Foo</span></li>
 </ol>
 !! end
 
@@ -22623,16 +23037,16 @@ B <ref group="X" name="b" />
 <ref name="b">foo</ref>
 </references>
 !! html/parsoid
-<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
-B <span about="#mwt4" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}'><a href="#cite_note-b-2" data-mw-group="X"><span class="mw-reflink-text">[X 1]</span></a></span>
+<p>A <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
+B <span about="#mwt4" class="mw-ref" id="cite_ref-b_2-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","attrs":{"group":"X","name":"b"}}'><a href="./Main_Page#cite_note-b-2" data-mw-group="X"><span class="mw-reflink-text">[X 1]</span></a></span>
 </p>
 
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo bar for a</span></li>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo bar for a</span></li>
 </ol>
 
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw-group="X" data-mw='{"name":"references","attrs":{"group":"X"},"body":{"html":"\n&lt;span about=\"#mwt10\" class=\"mw-ref\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[96,119,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-b-2\"},\"attrs\":{\"name\":\"b\"}}&#39;>&lt;a href=\"#cite_note-b-2\" style=\"counter-reset: mw-Ref 1;\" data-mw-group=\"X\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[X 1]&lt;/span>&lt;/a>&lt;/span>\n"}}'>
-<li about="#cite_note-b-2" id="cite_note-b-2"><a href="#cite_ref-b_2-0" data-mw-group="X" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">foo</span></li>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt8" data-mw-group="X" data-mw='{"name":"references","attrs":{"group":"X"},"body":{"html":"\n&lt;span about=\"#mwt10\" class=\"mw-ref\" rel=\"dc:references\" typeof=\"mw:Extension/ref\" data-parsoid=&#39;{\"dsr\":[96,119,14,6]}&#39; data-mw=&#39;{\"name\":\"ref\",\"body\":{\"id\":\"mw-reference-text-cite_note-b-2\"},\"attrs\":{\"name\":\"b\"}}&#39;>&lt;a href=\"./Main_Page#cite_note-b-2\" style=\"counter-reset: mw-Ref 1;\" data-mw-group=\"X\" data-parsoid=\"{}\">&lt;span class=\"mw-reflink-text\" data-parsoid=\"{}\">[X 1]&lt;/span>&lt;/a>&lt;/span>\n"}}'>
+<li about="#cite_note-b-2" id="cite_note-b-2"><a href="./Main_Page#cite_ref-b_2-0" data-mw-group="X" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-b-2" class="mw-reference-text">foo</span></li>
 </ol>
 !! end
 
@@ -22642,8 +23056,8 @@ References: 8. T88019: Remove <meta>s from templates inside <ref> that's itself
 X{{echo|<ref>foo {{echo|<b>bar</b>}} and {{echo|baz}} boo</ref>}}
 <references />
 !! html/parsoid
-<p>X<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;ref>foo {{echo|&lt;b>bar&lt;/b>}} and {{echo|baz}} boo&lt;/ref>"}},"i":0}}]}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt7" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <b data-parsoid='{"stx":"html"}'>bar</b> and baz boo</span></li>
+<p>X<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Transclusion  mw:Extension/ref" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"&lt;ref>foo {{echo|&lt;b>bar&lt;/b>}} and {{echo|baz}} boo&lt;/ref>"}},"i":0}}]}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt7" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo <b data-parsoid='{"stx":"html"}'>bar</b> and baz boo</span></li>
 </ol>
 !!end
 
@@ -22657,12 +23071,12 @@ References: 9. Generate missing references list at the end
 A <ref>foo</ref>
 B <ref group="inexistent">bar</ref>
 !! html/parsoid
-<p>A <span class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B <span class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"inexistent"}}'><a href="#cite_note-2" data-mw-group="inexistent"><span class="mw-reflink-text">[inexistent 1]</span></a></span></p>
+<p>A <span class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> B <span class="mw-ref" id="cite_ref-2" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-2"},"attrs":{"group":"inexistent"}}'><a href="./Main_Page#cite_note-2" data-mw-group="inexistent"><span class="mw-reflink-text">[inexistent 1]</span></a></span></p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{},"autoGenerated":true}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li>
 </ol>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt6" data-mw-group="inexistent" data-mw='{"name":"references","attrs":{"group":"inexistent"},"autoGenerated":true}'>
-<li about="#cite_note-2" id="cite_note-2"><a href="#cite_ref-2" data-mw-group="inexistent" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
+<li about="#cite_note-2" id="cite_note-2"><a href="./Main_Page#cite_ref-2" data-mw-group="inexistent" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-2" class="mw-reference-text">bar</span></li>
 </ol>
 !! end
 
@@ -22688,9 +23102,9 @@ Entities in ref name
 <ref name="test &amp; me">hi</ref>
 <references />
 !! html/parsoid
-<p><span about="#mwt2" class="mw-ref" id="cite_ref-test_.26_me_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-test_.26_me-1"},"attrs":{"name":"test &amp;amp; me"}}'><a href="#cite_note-test_.26_me-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p><span about="#mwt2" class="mw-ref" id="cite_ref-test_.26_me_1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-test_.26_me-1"},"attrs":{"name":"test &amp;amp; me"}}'><a href="./Main_Page#cite_note-test_.26_me-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-test_.26_me-1" id="cite_note-test_.26_me-1"><a href="#cite_ref-test_.26_me_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-test_.26_me-1" class="mw-reference-text">hi</span></li>
+<li about="#cite_note-test_.26_me-1" id="cite_note-test_.26_me-1"><a href="./Main_Page#cite_ref-test_.26_me_1-0" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-test_.26_me-1" class="mw-reference-text">hi</span></li>
 </ol>
 !! end
 
@@ -22708,10 +23122,10 @@ a<ref>foo</ref>
 
 <references>
 !! html/parsoid
-<p>a<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>a<span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1" style="counter-reset: mw-Ref 1;"><span class="mw-reflink-text">[1]</span></a></span></p>
 
 <p>&lt;references></p>
-<ol class="mw-references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{},"autoGenerated":true}'><li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
+<ol class="mw-references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{},"autoGenerated":true}'><li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">foo</span></li></ol>
 !! end
 
 !! test
@@ -22731,10 +23145,14 @@ foo<ol class="mw-references" typeof="mw:Extension/references" about="#mwt2" data
 #### https://www.mediawiki.org/wiki/Parsoid/HTML_based_LST
 #### ----------------------------------------------------------------
 
+## We still need to support serializing the older format while content is stored.
 !! test
-LST Sections: 1. Simple section start and end
+LST Sections: Backwards compatibility
 !! options
-parsoid={ "suppressErrors": true }
+parsoid={
+  "suppressErrors": true,
+  "modes": ["html2wt"]
+}
 !! wikitext
 <section begin="2011-05-16" />
 <section end="2014-04-10 (MW 1.23wmf22)" />
@@ -22743,6 +23161,21 @@ parsoid={ "suppressErrors": true }
 <meta typeof="mw:Extension/LabeledSectionTransclusion/end" content="2014-04-10 (MW 1.23wmf22)"/></p>
 !! end
 
+## The unconventional output is the result of `usePHPPreProcessor` being
+## disabled in parserTests.js.  This test is mainly just to show <section> is
+## recognized as an extension tag w/o a native handler.
+!! test
+LST Sections: Newfangled approach
+!! options
+parsoid={ "suppressErrors": true }
+!! wikitext
+<section begin="2011-05-16" />
+<section end="2014-04-10 (MW 1.23wmf22)" />
+!! html/parsoid
+<p><span typeof="mw:Extension/section" about="#mwt1" data-parsoid='{"stx":"html","selfClose":true,"src":"&lt;section begin=\"2011-05-16\" />","tagWidths":[30,0]}'>&lt;section begin="2011-05-16" /></span>
+<span typeof="mw:Extension/section" about="#mwt2" data-parsoid='{"stx":"html","selfClose":true,"src":"&lt;section end=\"2014-04-10 (MW 1.23wmf22)\" />","tagWidths":[43,0]}'>&lt;section end="2014-04-10 (MW 1.23wmf22)" /></span></p>
+!! end
+
 #--------- Test stripping of empty nodes in template content ----------
 !!test
 Empty LI and TR nodes should be stripped from template content
@@ -24081,11 +24514,11 @@ parsoid=html2wt
 <i>a'</i> foo <i><a rel="mw:WikiLink" href="Bar" title="Bar">bar</a></i>
 <i>a'</i> foo <b><a rel="mw:WikiLink" href="Bar" title="Bar" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"echo","href":"./Template:Echo"},"params":{"1":{"wt":"[[bar]]"}},"i":0}}]}'>bar</a></b>
 <a rel="mw:WikiLink" href="Foo" title="Foo">foo</a> x'<i><a href="Bar" rel="mw:WikiLink" title="Bar">bar</a></i>
-'<i>foo</i> <span class="mw-ref" id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
+'<i>foo</i> <span class="mw-ref" id="cite_ref-1-0" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span>
 '<i>foo</i> <div title="name">test</div>
 '<i>foo</i> and <br data-parsoid='{"stx":"html","noClose":true}'/> bar
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt5" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">test</span></li>
+<li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">test</span></li>
 </ol>
 !! wikitext
 '''a'' foo ''[[bar]]''
 !! options
 parsoid=html2wt
 !! html/parsoid
-<p>foo <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
+<p>foo <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span></p>
 <ol class="mw-references" typeof="mw:Extension/references" about="#mwt4" data-mw='{"name":"references","attrs":{}}'>
-<li about="#cite_note-1" id="cite_note-1"><a href="#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"><i>a</i>
+<li about="#cite_note-1" id="cite_note-1"><a href="./Main_Page#cite_ref-1" rel="mw:referencedBy"><span class="mw-linkback-text">↑ </span></a> <span id="mw-reference-text-cite_note-1" class="mw-reference-text"><i>a</i>
  b</span></li>
 </ol>
 !! wikitext
@@ -25741,9 +26174,9 @@ parsoid={
   "scrubWikitext": true
 }
 !! html/parsoid
-<h2> foo <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> </h2>
+<h2> foo <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> </h2>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">bar <link rel="mw:PageProp/Category" href="./Category:Baz" /> </span></li></ol>
+<ol class="references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text">bar <link rel="mw:PageProp/Category" href="./Category:Baz" /> </span></li></ol>
 !! wikitext
 == foo <ref>bar 
 [[Category:Baz]] </ref> ==
@@ -25831,9 +26264,9 @@ parsoid=html2wt
 <h2> hi <span about="#mwt1" typeof="mw:Transclusion" data-mw='{"parts":[{"template":{"target":{"wt":"bogus","href":"./Template:Bogus"},"params":{"1":{"wt":"there\nyou"}},"i":0}}]}'>there</span><span about="#mwt1">
 </span><span about="#mwt1">you</span> </h2>
 
-<h2> foo <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> </h2>
+<h2> foo <span about="#mwt2" class="mw-ref" id="cite_ref-1" rel="dc:references" typeof="mw:Extension/ref" data-mw='{"name":"ref","body":{"id":"mw-reference-text-cite_note-1"},"attrs":{}}'><a href="./Main_Page#cite_note-1"><span class="mw-reflink-text">[1]</span></a></span> </h2>
 
-<ol class="references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">hello
+<ol class="references" typeof="mw:Extension/references" about="#mwt3" data-mw='{"name":"references","attrs":{}}'><li about="#cite_note-1" id="cite_note-1"><span rel="mw:referencedBy"><a href="./Main_Page#cite_ref-1">↑</a></span> <span id="mw-reference-text-cite_note-1" class="mw-reference-text" data-parsoid="{}">hello
 there</span></li></ol>
 
 <ul><li>asd
@@ -26395,6 +26828,100 @@ parsoid=html2wt,wt2wt
 </table>
 !! end
 
+!! test
+T149209: WTS: Handle newlines in table cells properly
+!! options
+parsoid=html2wt
+!! html/parsoid
+<table>
+<tbody>
+<tr><td>a
+b
+</td><td data-parsoid='{"stx_v":"row"}'>c</td></tr>
+<tr><td><p>x</p>
+</td><td data-parsoid='{"stx_v":"row", "startTagSrc": "{{!}}{{!}}"}'>y</td></tr>
+</tbody></table>
+<table>
+<tbody>
+<tr><th>a
+b
+</th><th data-parsoid='{"stx_v":"row"}'>c</th></tr>
+<tr><th><p>x</h>
+</th><th data-parsoid='{"stx_v":"row"}'>y</th></tr>
+</tbody></table>
+!! wikitext
+{|
+|a
+b
+|c
+|-
+|x
+{{!}}y
+|}
+{|
+!a
+b
+!c
+|-
+!x
+!y
+|}
+!! end
+
+!! test
+T149209: Selser: Handle newlines in table cells properly
+!! options
+parsoid={
+  "modes": ["selser"],
+  "changes": [
+    [ "#h1", "html", "a\nb\n" ],
+    [ "#h2", "html", "a\nb\n" ],
+    [ "#c1", "html", "a\nb\n" ],
+    [ "#c2", "html", "<p>a</p>" ],
+    [ "#c3", "html", "<p>a</p>" ],
+    [ "#c4", "html", "edit-me<p>a</p>" ]
+  ]
+}
+!! wikitext
+{|
+! id="h1" |edit-me!!1
+|-
+! id="h2" |edit-me||2
+|-
+| id="c1" |edit-me||3
+|-
+| id="c2" |edit-me||4
+|-
+| id="c3" |edit-me||p||q||r
+|-
+| id="c4" |edit-me||p||q||r
+|}
+!! wikitext/edited
+{|
+! id="h1" |a
+b
+!1
+|-
+! id="h2" |a
+b
+!2
+|-
+| id="c1" |a
+b
+|3
+|-
+| id="c2" |a
+|4
+|-
+| id="c3" |a
+|p||q||r
+|-
+| id="c4" |edit-me
+a
+|p||q||r
+|}
+!! end
+
 !! test
 HTML id attribute with Parsoid-like element ids should not be serialized to wikitext
 !! options
index cfaf9a1..5d42cf5 100755 (executable)
@@ -1,4 +1,11 @@
-#!/bin/sh
+#!/bin/bash
+
+# mediawiki-vagrant installs dont have realpath by default
+if ! which realpath > /dev/null; then
+       realpath() {
+               php -r "echo realpath('$*');"
+       }
+fi
 
 # Note that this isn't loaded in via composer because then composer can
 # only be run with php7.0
@@ -8,30 +15,55 @@ if [ ! -f "$PHAN" ]; then
        exit 1
 fi
 
-cd "$(dirname "$0")"
+if [ -z "$MW_INSTALL_PATH" ]; then
+       # Figure out where mediawiki is based on the location of this script
+       pushd "$(dirname "$0")" > /dev/null
+       export MW_INSTALL_PATH="$(git rev-parse --show-toplevel)"
+       popd >/dev/null
+fi
+
+# If the first argument doesn't start with a -, then it's a path
+# to another project (extension, skin, etc.) to analyze
+if [[ "$1" != "-"* ]]; then
+       cd $1
+       shift
+else
+       cd "$(dirname "$0")"
+fi
 
 # Root directory of project
 export ROOT="$(git rev-parse --show-toplevel)"
 
-# Phan's issues directory
-export ISSUES="${ROOT}/tests/phan/issues"
-
 # Go to the root of this git repo
 cd "$ROOT"
 
+export CONFIG_FILE="$ROOT/tests/phan/config.php"
+if [ ! -f "$CONFIG_FILE" ]; then
+       echo "Could not find a phan config file to apply in"
+       echo "$CONFIG_FILE"
+       exit 1
+fi
+
+# Phan's issues directory
+export ISSUES="${ROOT}/tests/phan/issues"
+mkdir -p "$ISSUES"
+
 # Get the current hash of HEAD
 export REV="$(git rev-parse HEAD)"
 
 # Destination for issues found
 export RUN="${ISSUES}/issues-${REV}"
 
+
 # Run the analysis, emitting output to the
 # issues file.
 php7.0 $PHAN \
        --project-root-directory "$ROOT" \
-       --config-file "$ROOT/tests/phan/config.php" \
-       --output "$ROOT/tests/phan/issues/issues-${REV}" \
-       "${@}"
+       --config-file "$CONFIG_FILE" \
+       --output "php://stdout" \
+       "${@}" \
+       | php "$MW_INSTALL_PATH/tests/phan/bin/postprocess-phan.php" "${@}" \
+       > $RUN
 
 EXIT_CODE="$?"
 
diff --git a/tests/phan/bin/postprocess-phan.php b/tests/phan/bin/postprocess-phan.php
new file mode 100644 (file)
index 0000000..3e80598
--- /dev/null
@@ -0,0 +1,146 @@
+<?php
+
+abstract class Suppressor {
+       /**
+        * @param string $input
+        * @return bool do errors remain
+        */
+       abstract public function suppress( $input );
+
+       /**
+        * @param string[] $source
+        * @param string $type
+        * @param int $lineno
+        * @return bool
+        */
+       protected function isSuppressed( array $source, $type, $lineno ) {
+               return $lineno > 0 && preg_match(
+                       "|/\*\* @suppress {$type} |",
+                       $source[$lineno - 1]
+               );
+       }
+}
+
+class TextSuppressor extends Suppressor {
+       /**
+        * @param string $input
+        * @return bool do errors remain
+        */
+       public function suppress( $input ) {
+               $hasErrors = false;
+               $errors = [];
+               foreach ( explode( "\n", $input ) as $error ) {
+                       if ( empty( $error ) ) {
+                               continue;
+                       }
+                       if ( !preg_match( '/^(.*):(\d+) (Phan\w+) (.*)$/', $error, $matches ) ) {
+                               echo "Failed to parse line: $error\n";
+                               continue;
+                       }
+                       list( $source, $file, $lineno, $type, $message ) = $matches;
+                       $errors[$file][] = [
+                               'orig' => $error,
+                               // convert from 1 indexed to 0 indexed
+                               'lineno' => $lineno - 1,
+                               'type' => $type,
+                       ];
+               }
+               foreach ( $errors  as $file => $fileErrors ) {
+                       $source = file( $file );
+                       foreach ( $fileErrors as $error ) {
+                               if ( !$this->isSuppressed( $source, $error['type'], $error['lineno'] ) ) {
+                                       echo $error['orig'], "\n";
+                                       $hasErrors = true;
+                               }
+                       }
+               }
+
+               return $hasErrors;
+       }
+}
+
+class CheckStyleSuppressor extends Suppressor {
+       /**
+        * @param string $input
+        * @return bool True do errors remain
+        */
+       public function suppress( $input ) {
+               $dom = new DOMDocument();
+               $dom->loadXML( $input );
+               $hasErrors = false;
+               // DOMNodeList's are "live", convert to an array so it works as expected
+               $files = [];
+               foreach ( $dom->getElementsByTagName( 'file' ) as $file ) {
+                       $files[] = $file;
+               }
+               foreach ( $files as $file ) {
+                       $errors = [];
+                       foreach ( $file->getElementsByTagName( 'error' ) as $error ) {
+                               $errors[] = $error;
+                       }
+                       $source = file( $file->getAttribute( 'name' ) );
+                       $fileHasErrors = false;
+                       foreach ( $errors as $error ) {
+                               $lineno = $error->getAttribute( 'line' ) - 1;
+                               $type = $error->getAttribute( 'source' );
+                               if ( $this->isSuppressed( $source, $type, $lineno ) ) {
+                                       $error->parentNode->removeChild( $error );
+                               } else {
+                                       $fileHasErrors = true;
+                                       $hasErrors = true;
+                               }
+                       }
+                       if ( !$fileHasErrors ) {
+                               $file->parentNode->removeChild( $file );
+                       }
+               }
+               echo $dom->saveXML();
+
+               return $hasErrors;
+       }
+}
+
+class NoopSuppressor extends Suppressor {
+       private $mode;
+
+       public function __construct( $mode ) {
+               $this->mode = $mode;
+       }
+       public function suppress( $input ) {
+               echo "Unsupported output mode: {$this->mode}\n$input";
+               return true;
+       }
+}
+
+$opt = getopt( "m:", [ "output-mode:" ] );
+// if provided multiple times getopt returns an array
+if ( isset( $opt['m'] ) ) {
+       $mode = $opt['m'];
+} elseif ( isset( $mode['output-mode'] ) ) {
+       $mode = $opt['output-mode'];
+} else {
+       $mode = 'text';
+}
+if ( is_array( $mode ) ) {
+       // If an option is passed multiple times getopt returns an
+       // array. Just take the last one.
+       $mode = end( $mode );
+}
+
+switch ( $mode ) {
+case 'text':
+       $suppressor = new TextSuppressor();
+       break;
+case 'checkstyle':
+       $suppressor = new CheckStyleSuppressor();
+       break;
+default:
+       $suppressor = new NoopSuppressor( $mode );
+}
+
+$input = file_get_contents( 'php://stdin' );
+$hasErrors = $suppressor->suppress( $input );
+
+if ( $hasErrors ) {
+       exit( 1 );
+}
index 7d4cfb9..14ff52a 100644 (file)
@@ -95,6 +95,8 @@ return [
                'maintenance/language/',
                // External class
                'includes/libs/jsminplus.php',
+               // separate repositories
+               'skins/'
        ],
 
        /**
@@ -165,8 +167,10 @@ return [
         */
        'analyze_signature_compatibility' => true,
 
-       // Only emit critical issues
-       "minimum_severity" => 10,
+       // Emit all issues. They are then supressed via
+       // suppress_issue_types, rather than a minimum
+       // severity.
+       "minimum_severity" => 0,
 
        /**
         * If true, missing properties will be created when
@@ -289,14 +293,54 @@ return [
         * to this black-list to inhibit them from being reported.
         */
        'suppress_issue_types' => [
-               // MediaWiki has so much deprecated class usage it's a bit hopeless to
-               // fix this immediately
-               'PhanDeprecatedClass',
-               'PhanDeprecatedFunction',
-               'PhanDeprecatedProperty',
-               // There are arround 1400 usages of undeclared properties.
-               // php is ok with that but it's a code smell.
-               'PhanUndeclaredProperty',
+               // approximate error count: 8
+               "PhanDeprecatedClass",
+               // approximate error count: 441
+               "PhanDeprecatedFunction",
+               // approximate error count: 24
+               "PhanDeprecatedProperty",
+               // approximate error count: 12
+               "PhanParamReqAfterOpt",
+               // approximate error count: 748
+               "PhanParamSignatureMismatch",
+               // approximate error count: 7
+               "PhanParamSignatureMismatchInternal",
+               // approximate error count: 308
+               "PhanParamTooMany",
+               // approximate error count: 3
+               "PhanParamTooManyInternal",
+               // approximate error count: 1
+               "PhanRedefineFunctionInternal",
+               // approximate error count: 2
+               "PhanTraitParentReference",
+               // approximate error count: 4
+               "PhanTypeComparisonFromArray",
+               // approximate error count: 3
+               "PhanTypeInvalidRightOperand",
+               // approximate error count: 563
+               "PhanTypeMismatchArgument",
+               // approximate error count: 39
+               "PhanTypeMismatchArgumentInternal",
+               // approximate error count: 16
+               "PhanTypeMismatchForeach",
+               // approximate error count: 63
+               "PhanTypeMismatchProperty",
+               // approximate error count: 95
+               "PhanTypeMismatchReturn",
+               // approximate error count: 11
+               "PhanTypeMissingReturn",
+               // approximate error count: 5
+               "PhanTypeNonVarPassByRef",
+               // approximate error count: 27
+               "PhanUndeclaredConstant",
+               // approximate error count: 185
+               "PhanUndeclaredMethod",
+               // approximate error count: 1342
+               "PhanUndeclaredProperty",
+               // approximate error count: 9
+               "PhanUndeclaredStaticMethod",
+               // approximate error count: 79
+               "PhanUndeclaredVariable",
        ],
 
        /**
index db1df5c..fd02a3e 100644 (file)
@@ -582,6 +582,10 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        /**
         * Make sure MediaWikiTestCase extending classes have called their
         * parent setUp method
+        *
+        * With strict coverage activated in PHP_CodeCoverage, this test would be
+        * marked as risky without the following annotation (T152923).
+        * @coversNothing
         */
        final public function testMediaWikiTestCaseParentSetupCalled() {
                $this->assertArrayHasKey( 'setUp', $this->called,
@@ -1087,11 +1091,11 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
         * Clones all tables in the given database (whatever database that connection has
         * open), to versions with the test prefix.
         *
-        * @param Database $db Database to use
+        * @param IMaintainableDatabase $db Database to use
         * @param string $prefix Prefix to use for test tables
         * @return bool True if tables were cloned, false if only the prefix was changed
         */
-       protected static function setupDatabaseWithTestPrefix( Database $db, $prefix ) {
+       protected static function setupDatabaseWithTestPrefix( IMaintainableDatabase $db, $prefix ) {
                $tablesCloned = self::listTables( $db );
                $dbClone = new CloneDatabase( $db, $tablesCloned, $prefix );
                $dbClone->useTemporaryTables( self::$useTemporaryTables );
@@ -1210,9 +1214,7 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                                list( $proto, $cluster ) = explode( '://', $url, 2 );
                                // Avoid getMaster() because setupDatabaseWithTestPrefix()
                                // requires Database instead of plain DBConnRef/IDatabase
-                               $lb = $externalStoreDB->getLoadBalancer( $cluster );
-                               $dbw = $lb->getConnection( DB_MASTER );
-                               $dbws[] = $dbw;
+                               $dbws[] = $externalStoreDB->getMaster( $cluster );
                        }
                }
 
@@ -1326,11 +1328,11 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
        /**
         * @since 1.18
         *
-        * @param Database $db
+        * @param IMaintainableDatabase $db
         *
         * @return array
         */
-       public static function listTables( Database $db ) {
+       public static function listTables( IMaintainableDatabase $db ) {
                $prefix = $db->tablePrefix();
                $tables = $db->listTables( $prefix, __METHOD__ );
 
@@ -1378,6 +1380,8 @@ abstract class MediaWikiTestCase extends PHPUnit_Framework_TestCase {
                if ( isset( PHPUnitMaintClass::$additionalOptions[$offset] ) ) {
                        return PHPUnitMaintClass::$additionalOptions[$offset];
                }
+
+               return null;
        }
 
        /**
index 45cfdbf..68b91bf 100644 (file)
@@ -14,9 +14,12 @@ abstract class ResourceLoaderTestCase extends MediaWikiTestCase {
         * @param array|string $options Language code or options array
         * - string 'lang' Language code
         * - string 'dir' Language direction (ltr or rtl)
+        * - string 'modules' Pipe-separated list of module names
+        * - string|null 'only' "scripts" (unwrapped script), "styles" (stylesheet), or null
+        *    (mw.loader.implement).
         * @return ResourceLoaderContext
         */
-       protected function getResourceLoaderContext( $options = [] ) {
+       protected function getResourceLoaderContext( $options = [], ResourceLoader $rl = null ) {
                if ( is_string( $options ) ) {
                        // Back-compat for extension tests
                        $options = [ 'lang' => $options ];
@@ -24,12 +27,14 @@ abstract class ResourceLoaderTestCase extends MediaWikiTestCase {
                $options += [
                        'lang' => 'en',
                        'dir' => 'ltr',
+                       'modules' => 'startup',
+                       'only' => 'scripts',
                ];
-               $resourceLoader = new ResourceLoader();
+               $resourceLoader = $rl ?: new ResourceLoader();
                $request = new FauxRequest( [
                                'lang' => $options['lang'],
-                               'modules' => 'startup',
-                               'only' => 'scripts',
+                               'modules' => $options['modules'],
+                               'only' => $options['only'],
                                'skin' => 'vector',
                                'target' => 'phpunit',
                ] );
@@ -151,6 +156,12 @@ class EmptyResourceLoader extends ResourceLoader {
        public function __construct( Config $config = null, LoggerInterface $logger = null ) {
                $this->setLogger( $logger ?: new NullLogger() );
                $this->config = $config ?: MediaWikiServices::getInstance()->getMainConfig();
+               // Source "local" is required by StartupModule
+               $this->addSource( 'local', $this->config->get( 'LoadScript' ) );
                $this->setMessageBlobStore( new MessageBlobStore( $this, $this->getLogger() ) );
        }
+
+       public function getErrors() {
+               return $this->errors;
+       }
 }
index 9f38659..12b277e 100644 (file)
@@ -409,4 +409,33 @@ class BlockTest extends MediaWikiLangTestCase {
                        "Account creation should not be blocked by default"
                );
        }
+
+       public function testSystemBlocks() {
+               $blockOptions = [
+                       'address' => 'UTBlockee',
+                       'reason' => 'test system block',
+                       'timestamp' => wfTimestampNow(),
+                       'expiry' => $this->db->getInfinity(),
+                       'byText' => 'MetaWikiUser',
+                       'systemBlock' => 'test',
+                       'enableAutoblock' => true,
+               ];
+               $block = new Block( $blockOptions );
+
+               $this->assertSame( 'test', $block->getSystemBlockType() );
+
+               try {
+                       $block->insert();
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( MWException $ex ) {
+                       $this->assertSame( 'Cannot insert a system block into the database', $ex->getMessage() );
+               }
+
+               try {
+                       $block->doAutoblock( '192.0.2.2' );
+                       $this->fail( 'Expected exception not thrown' );
+               } catch ( MWException $ex ) {
+                       $this->assertSame( 'Cannot autoblock from a system block', $ex->getMessage() );
+               }
+       }
 }
index 4fe806c..1de9c23 100644 (file)
@@ -51,6 +51,10 @@ class MessageTest extends MediaWikiLangTestCase {
                                [],
                                [],
                        ],
+                       [
+                               [],
+                               [ [] ],
+                       ],
                        [
                                [ 'foo' ],
                                [ 'foo' ],
@@ -68,19 +72,37 @@ class MessageTest extends MediaWikiLangTestCase {
                                [ [ 'baz', 'foo' ] ],
                        ],
                        [
-                               [ 'baz', 'foo' ],
+                               [ Message::rawParam( 'baz' ) ],
+                               [ Message::rawParam( 'baz' ) ],
+                       ],
+                       [
+                               [ Message::rawParam( 'baz' ), 'foo' ],
+                               [ Message::rawParam( 'baz' ), 'foo' ],
+                       ],
+                       [
+                               [ Message::rawParam( 'baz' ) ],
+                               [ [ Message::rawParam( 'baz' ) ] ],
+                       ],
+                       [
+                               [ Message::rawParam( 'baz' ), 'foo' ],
+                               [ [ Message::rawParam( 'baz' ), 'foo' ] ],
+                       ],
+
+                       // Test handling of erroneous input, to detect if it changes
+                       [
+                               [ [ 'baz', 'foo' ], 'hhh' ],
                                [ [ 'baz', 'foo' ], 'hhh' ],
                        ],
                        [
-                               [ 'baz', 'foo' ],
+                               [ [ 'baz', 'foo' ], 'hhh', [ 'ahahahahha' ] ],
                                [ [ 'baz', 'foo' ], 'hhh', [ 'ahahahahha' ] ],
                        ],
                        [
-                               [ 'baz', 'foo' ],
+                               [ [ 'baz', 'foo' ], [ 'ahahahahha' ] ],
                                [ [ 'baz', 'foo' ], [ 'ahahahahha' ] ],
                        ],
                        [
-                               [ 'baz' ],
+                               [ [ 'baz' ], [ 'ahahahahha' ] ],
                                [ [ 'baz' ], [ 'ahahahahha' ] ],
                        ],
                ];
@@ -192,6 +214,14 @@ class MessageTest extends MediaWikiLangTestCase {
        public function testWfMessageParams() {
                $this->assertSame( 'Return to $1.', wfMessage( 'returnto' )->text() );
                $this->assertSame( 'Return to $1.', wfMessage( 'returnto', [] )->text() );
+               $this->assertSame(
+                       'Return to 1,024.',
+                       wfMessage( 'returnto', Message::numParam( 1024 ) )->text()
+               );
+               $this->assertSame(
+                       'Return to 1,024.',
+                       wfMessage( 'returnto', [ Message::numParam( 1024 ) ] )->text()
+               );
                $this->assertSame(
                        'You have foo (bar).',
                        wfMessage( 'youhavenewmessages', 'foo', 'bar' )->text()
@@ -200,6 +230,27 @@ class MessageTest extends MediaWikiLangTestCase {
                        'You have foo (bar).',
                        wfMessage( 'youhavenewmessages', [ 'foo', 'bar' ] )->text()
                );
+               $this->assertSame(
+                       'You have 1,024 (bar).',
+                       wfMessage(
+                               'youhavenewmessages',
+                               Message::numParam( 1024 ), 'bar'
+                       )->text()
+               );
+               $this->assertSame(
+                       'You have foo (2,048).',
+                       wfMessage(
+                               'youhavenewmessages',
+                               'foo', Message::numParam( 2048 )
+                       )->text()
+               );
+               $this->assertSame(
+                       'You have 1,024 (2,048).',
+                       wfMessage(
+                               'youhavenewmessages',
+                               [ Message::numParam( 1024 ), Message::numParam( 2048 ) ]
+                       )->text()
+               );
        }
 
        /**
index 3cb20e1..7086a92 100644 (file)
@@ -33,16 +33,18 @@ use Psr\Log\LogLevel;
  */
 class TestLogger extends \Psr\Log\AbstractLogger {
        private $collect = false;
+       private $collectContext = false;
        private $buffer = [];
        private $filter = null;
 
        /**
         * @param bool $collect Whether to collect logs
         * @param callable $filter Filter logs before collecting/printing. Signature is
-        *  string|null function ( string $message, string $level );
+        *  string|null function ( string $message, string $level, array $context );
         */
-       public function __construct( $collect = false, $filter = null ) {
+       public function __construct( $collect = false, $filter = null, $collectContext = false ) {
                $this->collect = $collect;
+               $this->collectContext = $collectContext;
                $this->filter = $filter;
        }
 
@@ -56,7 +58,8 @@ class TestLogger extends \Psr\Log\AbstractLogger {
 
        /**
         * Return the collected logs
-        * @return array Array of array( string $level, string $message )
+        * @return array Array of array( string $level, string $message ), or
+        *   array( string $level, string $message, array $context ) if $collectContext was true.
         */
        public function getBuffer() {
                return $this->buffer;
@@ -73,14 +76,18 @@ class TestLogger extends \Psr\Log\AbstractLogger {
                $message = trim( $message );
 
                if ( $this->filter ) {
-                       $message = call_user_func( $this->filter, $message, $level );
+                       $message = call_user_func( $this->filter, $message, $level, $context );
                        if ( $message === null ) {
                                return;
                        }
                }
 
                if ( $this->collect ) {
-                       $this->buffer[] = [ $level, $message ];
+                       if ( $this->collectContext ) {
+                               $this->buffer[] = [ $level, $message, $context ];
+                       } else {
+                               $this->buffer[] = [ $level, $message ];
+                       }
                } else {
                        switch ( $level ) {
                                case LogLevel::DEBUG:
index 5ecdf56..9121178 100644 (file)
@@ -787,5 +787,21 @@ class TitlePermissionTest extends MediaWikiLangTestCase {
                # $action != 'read' && $action != 'createaccount' && $user->isBlockedFrom( $this )
                #   $user->blockedFor() == ''
                #   $user->mBlock->mExpiry == 'infinity'
+
+               $this->user->mBlockedby = $this->user->getName();
+               $this->user->mBlock = new Block( [
+                       'address' => '127.0.8.1',
+                       'by' => $this->user->getId(),
+                       'reason' => 'no reason given',
+                       'timestamp' => $now,
+                       'auto' => false,
+                       'expiry' => 10,
+                       'systemBlock' => 'test',
+               ] );
+               $this->assertEquals( [ [ 'systemblockedtext',
+                               '[[User:Useruser|Useruser]]', 'no reason given', '127.0.0.1',
+                               'Useruser', 'test', '23:00, 31 December 1969', '127.0.8.1',
+                               $wgLang->timeanddate( wfTimestamp( TS_MW, $now ), true ) ] ],
+                       $this->title->getUserPermissionsErrors( 'move-target', $this->user ) );
        }
 }
index ba47059..0bd0bcc 100644 (file)
@@ -2404,6 +2404,35 @@ class WatchedItemStoreUnitTest extends MediaWikiTestCase {
                );
        }
 
+       public function testSetNotificationTimestampsForUser_nullTimestamp() {
+               $user = $this->getMockNonAnonUserWithId( 1 );
+               $timestamp = null;
+
+               $mockDb = $this->getMockDb();
+               $mockDb->expects( $this->once() )
+                       ->method( 'update' )
+                       ->with(
+                               'watchlist',
+                               [ 'wl_notificationtimestamp' => null ],
+                               [ 'wl_user' => 1 ]
+                       )
+                       ->will( $this->returnValue( true ) );
+               $mockDb->expects( $this->exactly( 0 ) )
+                       ->method( 'timestamp' )
+                       ->will( $this->returnCallback( function( $value ) {
+                               return 'TS' . $value . 'TS';
+                       } ) );
+
+               $store = $this->newWatchedItemStore(
+                       $this->getMockLoadBalancer( $mockDb ),
+                       $this->getMockCache()
+               );
+
+               $this->assertTrue(
+                       $store->setNotificationTimestampsForUser( $user, $timestamp )
+               );
+       }
+
        public function testSetNotificationTimestampsForUser_specificTargets() {
                $user = $this->getMockNonAnonUserWithId( 1 );
                $timestamp = '20100101010101';
index 96f3e44..7327e85 100644 (file)
@@ -135,11 +135,13 @@ class ApiBaseTest extends ApiTestCase {
                $expect = Status::newGood();
                $expect->fatal( 'blockedtext' );
                $expect->fatal( 'autoblockedtext' );
+               $expect->fatal( 'systemblockedtext' );
                $expect->fatal( 'mainpage' );
                $expect->fatal( 'parentheses', 'foobar' );
                $this->assertEquals( $expect, $mock->errorArrayToStatus( [
                        [ 'blockedtext' ],
                        [ 'autoblockedtext' ],
+                       [ 'systemblockedtext' ],
                        'mainpage',
                        [ 'parentheses', 'foobar' ],
                ] ) );
@@ -158,11 +160,13 @@ class ApiBaseTest extends ApiTestCase {
                $expect = Status::newGood();
                $expect->fatal( ApiMessage::create( 'apierror-blocked', 'blocked', $blockinfo ) );
                $expect->fatal( ApiMessage::create( 'apierror-autoblocked', 'autoblocked', $blockinfo ) );
+               $expect->fatal( ApiMessage::create( 'apierror-systemblocked', 'blocked', $blockinfo ) );
                $expect->fatal( 'mainpage' );
                $expect->fatal( 'parentheses', 'foobar' );
                $this->assertEquals( $expect, $mock->errorArrayToStatus( [
                        [ 'blockedtext' ],
                        [ 'autoblockedtext' ],
+                       [ 'systemblockedtext' ],
                        'mainpage',
                        [ 'parentheses', 'foobar' ],
                ], $user ) );
index 1b7f6bf..a40db24 100644 (file)
@@ -504,4 +504,116 @@ class ApiErrorFormatterTest extends MediaWikiLangTestCase {
                );
        }
 
+       /**
+        * @dataProvider provideGetMessageFromException
+        * @covers ApiErrorFormatter::getMessageFromException
+        * @covers ApiErrorFormatter::formatException
+        * @param Exception $exception
+        * @param array $options
+        * @param array $expect
+        */
+       public function testGetMessageFromException( $exception, $options, $expect ) {
+               $result = new ApiResult( 8388608 );
+               $formatter = new ApiErrorFormatter( $result, Language::factory( 'en' ), 'html', false );
+
+               $msg = $formatter->getMessageFromException( $exception, $options );
+               $this->assertInstanceOf( Message::class, $msg );
+               $this->assertInstanceOf( IApiMessage::class, $msg );
+               $this->assertSame( $expect, [
+                       'text' => $msg->parse(),
+                       'code' => $msg->getApiCode(),
+                       'data' => $msg->getApiData(),
+               ] );
+
+               $expectFormatted = $formatter->formatMessage( $msg );
+               $formatted = $formatter->formatException( $exception, $options );
+               $this->assertSame( $expectFormatted, $formatted );
+       }
+
+       /**
+        * @dataProvider provideGetMessageFromException
+        * @covers ApiErrorFormatter_BackCompat::formatException
+        * @param Exception $exception
+        * @param array $options
+        * @param array $expect
+        */
+       public function testGetMessageFromException_BC( $exception, $options, $expect ) {
+               $result = new ApiResult( 8388608 );
+               $formatter = new ApiErrorFormatter_BackCompat( $result );
+
+               $msg = $formatter->getMessageFromException( $exception, $options );
+               $this->assertInstanceOf( Message::class, $msg );
+               $this->assertInstanceOf( IApiMessage::class, $msg );
+               $this->assertSame( $expect, [
+                       'text' => $msg->parse(),
+                       'code' => $msg->getApiCode(),
+                       'data' => $msg->getApiData(),
+               ] );
+
+               $expectFormatted = $formatter->formatMessage( $msg );
+               $formatted = $formatter->formatException( $exception, $options );
+               $this->assertSame( $expectFormatted, $formatted );
+               $formatted = $formatter->formatException( $exception, $options + [ 'bc' => true ] );
+               $this->assertSame( $expectFormatted['info'], $formatted );
+       }
+
+       public static function provideGetMessageFromException() {
+               return [
+                       'Normal exception' => [
+                               new RuntimeException( '<b>Something broke!</b>' ),
+                               [],
+                               [
+                                       'text' => '&#60;b&#62;Something broke!&#60;/b&#62;',
+                                       'code' => 'internal_api_error_RuntimeException',
+                                       'data' => [],
+                               ]
+                       ],
+                       'Normal exception, wrapped' => [
+                               new RuntimeException( '<b>Something broke!</b>' ),
+                               [ 'wrap' => 'parentheses', 'code' => 'some-code', 'data' => [ 'foo' => 'bar', 'baz' => 42 ] ],
+                               [
+                                       'text' => '(&#60;b&#62;Something broke!&#60;/b&#62;)',
+                                       'code' => 'some-code',
+                                       'data' => [ 'foo' => 'bar', 'baz' => 42 ],
+                               ]
+                       ],
+                       'UsageException' => [
+                               new UsageException( '<b>Something broke!</b>', 'ue-code', 0, [ 'xxx' => 'yyy', 'baz' => 23 ] ),
+                               [],
+                               [
+                                       'text' => '&#60;b&#62;Something broke!&#60;/b&#62;',
+                                       'code' => 'ue-code',
+                                       'data' => [ 'xxx' => 'yyy', 'baz' => 23 ],
+                               ]
+                       ],
+                       'UsageException, wrapped' => [
+                               new UsageException( '<b>Something broke!</b>', 'ue-code', 0, [ 'xxx' => 'yyy', 'baz' => 23 ] ),
+                               [ 'wrap' => 'parentheses', 'code' => 'some-code', 'data' => [ 'foo' => 'bar', 'baz' => 42 ] ],
+                               [
+                                       'text' => '(&#60;b&#62;Something broke!&#60;/b&#62;)',
+                                       'code' => 'some-code',
+                                       'data' => [ 'xxx' => 'yyy', 'baz' => 42, 'foo' => 'bar' ],
+                               ]
+                       ],
+                       'LocalizedException' => [
+                               new LocalizedException( [ 'returnto', '<b>FooBar</b>' ] ),
+                               [],
+                               [
+                                       'text' => 'Return to <b>FooBar</b>.',
+                                       'code' => 'returnto',
+                                       'data' => [],
+                               ]
+                       ],
+                       'LocalizedException, wrapped' => [
+                               new LocalizedException( [ 'returnto', '<b>FooBar</b>' ] ),
+                               [ 'wrap' => 'parentheses', 'code' => 'some-code', 'data' => [ 'foo' => 'bar', 'baz' => 42 ] ],
+                               [
+                                       'text' => 'Return to <b>FooBar</b>.',
+                                       'code' => 'some-code',
+                                       'data' => [ 'foo' => 'bar', 'baz' => 42 ],
+                               ]
+                       ],
+               ];
+       }
+
 }
index d8282be..a4ca8a1 100644 (file)
@@ -43,9 +43,9 @@ class ApiRevisionDeleteTest extends ApiTestCase {
                $this->assertEquals( $out['status'], 'Success' );
                $this->assertArrayHasKey( 'items', $out );
                $item = $out['items'][0];
-               $this->assertArrayHasKey( 'userhidden', $item );
-               $this->assertArrayHasKey( 'commenthidden', $item );
-               $this->assertArrayHasKey( 'texthidden', $item );
+               $this->assertTrue( $item['userhidden'], 'userhidden' );
+               $this->assertTrue( $item['commenthidden'], 'commenthidden' );
+               $this->assertTrue( $item['texthidden'], 'texthidden' );
                $this->assertEquals( $item['id'], $revid );
 
                // Now check that that revision was actually hidden
@@ -70,9 +70,9 @@ class ApiRevisionDeleteTest extends ApiTestCase {
                $this->assertArrayHasKey( 'items', $out2 );
                $item = $out2['items'][0];
 
-               $this->assertArrayNotHasKey( 'userhidden', $item );
-               $this->assertArrayNotHasKey( 'commenthidden', $item );
-               $this->assertArrayNotHasKey( 'texthidden', $item );
+               $this->assertFalse( $item['userhidden'], 'userhidden' );
+               $this->assertFalse( $item['commenthidden'], 'commenthidden' );
+               $this->assertFalse( $item['texthidden'], 'texthidden' );
 
                $this->assertEquals( $item['id'], $revid );
 
@@ -107,11 +107,11 @@ class ApiRevisionDeleteTest extends ApiTestCase {
                $this->assertEquals( $out['status'], 'Success' );
                $this->assertArrayHasKey( 'items', $out );
                $item = $out['items'][0];
-               // Check it has userhidden & texthidden keys
-               // but no commenthidden key
-               $this->assertArrayHasKey( 'userhidden', $item );
-               $this->assertArrayNotHasKey( 'commenthidden', $item );
-               $this->assertArrayHasKey( 'texthidden', $item );
+               // Check it has userhidden & texthidden
+               // but not commenthidden
+               $this->assertTrue( $item['userhidden'], 'userhidden' );
+               $this->assertFalse( $item['commenthidden'], 'commenthidden' );
+               $this->assertTrue( $item['texthidden'], 'texthidden' );
                $this->assertEquals( $item['id'], $revid );
        }
 }
index 4dc8fec..baf8687 100644 (file)
@@ -63,7 +63,7 @@ class StoreBatchTest extends MediaWikiTestCase {
         * @param string $originalName The title of the image
         * @param string $srcPath The filepath or virtual URL
         * @param int $flags Flags to pass into repo::store().
-        * @return FileRepoStatus
+        * @return Status
         */
        private function storeit( $originalName, $srcPath, $flags ) {
                $hashPath = $this->repo->getHashPath( $originalName );
index e854ab5..43eb299 100644 (file)
@@ -1,10 +1,10 @@
 <?php
 /**
- * Specificly for testing Media handlers. Sets up a FSFile backend
+ * Specificly for testing Media handlers. Sets up a FileRepo backend
  */
 abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
 
-       /** @var FSRepo */
+       /** @var FileRepo */
        protected $repo;
        /** @var FSFileBackend */
        protected $backend;
@@ -29,7 +29,7 @@ abstract class MediaWikiMediaTestCase extends MediaWikiTestCase {
                        'containerPaths' => $containers,
                        'tmpDirectory' => $this->getNewTempDirectory()
                ] );
-               $this->repo = new FSRepo( $this->getRepoOptions() );
+               $this->repo = new FileRepo( $this->getRepoOptions() );
        }
 
        /**
diff --git a/tests/phpunit/includes/registration/CoreVersionCheckerTest.php b/tests/phpunit/includes/registration/CoreVersionCheckerTest.php
deleted file mode 100644 (file)
index 1dfcd82..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-
-/**
- * @covers CoreVersionChecker
- */
-class CoreVersionCheckerTest extends PHPUnit_Framework_TestCase {
-       /**
-        * @dataProvider provideCheck
-        */
-       public function testCheck( $coreVersion, $constraint, $expected ) {
-               $checker = new CoreVersionChecker( $coreVersion );
-               $this->assertEquals( $expected, $checker->check( $constraint ) );
-       }
-
-       public static function provideCheck() {
-               return [
-                       // [ $wgVersion, constraint, expected ]
-                       [ '1.25alpha', '>= 1.26', false ],
-                       [ '1.25.0', '>= 1.26', false ],
-                       [ '1.26alpha', '>= 1.26', true ],
-                       [ '1.26alpha', '>= 1.26.0', true ],
-                       [ '1.26alpha', '>= 1.26.0-stable', false ],
-                       [ '1.26.0', '>= 1.26.0-stable', true ],
-                       [ '1.26.1', '>= 1.26.0-stable', true ],
-                       [ '1.27.1', '>= 1.26.0-stable', true ],
-                       [ '1.26alpha', '>= 1.26.1', false ],
-                       [ '1.26alpha', '>= 1.26alpha', true ],
-                       [ '1.26alpha', '>= 1.25', true ],
-                       [ '1.26.0-alpha.14', '>= 1.26.0-alpha.15', false ],
-                       [ '1.26.0-alpha.14', '>= 1.26.0-alpha.10', true ],
-                       [ '1.26.1', '>= 1.26.2, <=1.26.0', false ],
-                       [ '1.26.1', '^1.26.2', false ],
-                       // Accept anything for un-parsable version strings
-                       [ '1.26mwf14', '== 1.25alpha', true ],
-                       [ 'totallyinvalid', '== 1.0', true ],
-               ];
-       }
-}
index 11995de..71f760d 100644 (file)
@@ -450,8 +450,9 @@ class ExtensionProcessorTest extends MediaWikiTestCase {
                $globalSettings = TestingAccessWrapper::newFromClass(
                        ExtensionProcessor::class )->globalSettings;
 
+               $version = ExtensionRegistry::MANIFEST_VERSION;
                $schema = FormatJson::decode(
-                       file_get_contents( "$IP/docs/extension.schema.json" ),
+                       file_get_contents( "$IP/docs/extension.schema.v$version.json" ),
                        true
                );
                $missing = [];
diff --git a/tests/phpunit/includes/registration/VersionCheckerTest.php b/tests/phpunit/includes/registration/VersionCheckerTest.php
new file mode 100644 (file)
index 0000000..9ee5881
--- /dev/null
@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * @covers VersionChecker
+ */
+class VersionCheckerTest extends PHPUnit_Framework_TestCase {
+       /**
+        * @dataProvider provideCheck
+        */
+       public function testCheck( $coreVersion, $constraint, $expected ) {
+               $checker = new VersionChecker( $coreVersion );
+               $this->assertEquals( $expected, !(bool)$checker->checkArray( [
+                       'FakeExtension' => [
+                               'MediaWiki' => $constraint,
+                       ],
+               ] )
+               );
+       }
+
+       public static function provideCheck() {
+               return [
+                       // [ $wgVersion, constraint, expected ]
+                       [ '1.25alpha', '>= 1.26', false ],
+                       [ '1.25.0', '>= 1.26', false ],
+                       [ '1.26alpha', '>= 1.26', true ],
+                       [ '1.26alpha', '>= 1.26.0', true ],
+                       [ '1.26alpha', '>= 1.26.0-stable', false ],
+                       [ '1.26.0', '>= 1.26.0-stable', true ],
+                       [ '1.26.1', '>= 1.26.0-stable', true ],
+                       [ '1.27.1', '>= 1.26.0-stable', true ],
+                       [ '1.26alpha', '>= 1.26.1', false ],
+                       [ '1.26alpha', '>= 1.26alpha', true ],
+                       [ '1.26alpha', '>= 1.25', true ],
+                       [ '1.26.0-alpha.14', '>= 1.26.0-alpha.15', false ],
+                       [ '1.26.0-alpha.14', '>= 1.26.0-alpha.10', true ],
+                       [ '1.26.1', '>= 1.26.2, <=1.26.0', false ],
+                       [ '1.26.1', '^1.26.2', false ],
+                       // Accept anything for un-parsable version strings
+                       [ '1.26mwf14', '== 1.25alpha', true ],
+                       [ 'totallyinvalid', '== 1.0', true ],
+               ];
+       }
+
+       /**
+        * @dataProvider provideType
+        */
+       public function testType( $given, $expected ) {
+               $checker = new VersionChecker( '1.0.0' );
+               $checker
+                       ->setLoadedExtensionsAndSkins( [
+                               'FakeDependency' => [
+                                       'version' => '1.0.0',
+                               ],
+                       ] );
+               $this->assertEquals( $expected, $checker->checkArray( [
+                       'FakeExtension' => $given,
+               ] )
+               );
+       }
+
+       public static function provideType() {
+               return [
+                       // valid type
+                       [
+                               [
+                                       'extensions' => [
+                                               'FakeDependency' => '1.0.0'
+                                       ]
+                               ],
+                               []
+                       ],
+                       [
+                               [
+                                       'MediaWiki' => '1.0.0'
+                               ],
+                               []
+                       ],
+               ];
+       }
+
+       /**
+        * Check, if a non-parsable version constraint does not throw an exception or
+        * returns any error message.
+        */
+       public function testInvalidConstraint() {
+               $checker = new VersionChecker( '1.0.0' );
+               $checker
+                       ->setLoadedExtensionsAndSkins( [
+                               'FakeDependency' => [
+                                       'version' => 'not really valid',
+                               ],
+                       ] );
+               $this->assertEquals( [ "FakeDependency does not have a valid version string." ],
+                       $checker->checkArray( [
+                               'FakeExtension' => [
+                                       'extensions' => [
+                                               'FakeDependency' => '1.24.3',
+                                       ],
+                               ],
+                       ] )
+               );
+
+               $checker = new VersionChecker( '1.0.0' );
+               $checker
+                       ->setLoadedExtensionsAndSkins( [
+                               'FakeDependency' => [
+                                       'version' => '1.24.3',
+                               ],
+                       ] );
+
+               $this->setExpectedException( 'UnexpectedValueException' );
+               $checker->checkArray( [
+                       'FakeExtension' => [
+                               'FakeDependency' => 'not really valid',
+                       ]
+               ] );
+       }
+}
index baf0b69..b658efb 100644 (file)
@@ -14,6 +14,7 @@ class ResourceLoaderContextTest extends PHPUnit_Framework_TestCase {
                        'ResourceLoaderDebug' => false,
                        'DefaultSkin' => 'fallback',
                        'LanguageCode' => 'nl',
+                       'LoadScript' => '/w/load.php',
                ] ) );
        }
 
index 1ecdf21..cde1e5a 100644 (file)
@@ -14,6 +14,10 @@ class ResourceLoaderTest extends ResourceLoaderTestCase {
                                'Foo' => '#eeeeee',
                                'bar' => 5,
                        ],
+                       // Clear ResourceLoaderGetConfigVars hooks (called by StartupModule)
+                       // to avoid notices during testMakeModuleResponse for missing
+                       // wgResourceLoaderLESSVars keys in extension hooks.
+                       'wgHooks' => [],
                ] );
        }
 
@@ -441,4 +445,135 @@ mw.example();
                        $this->assertTrue( true );
                }
        }
+
+       protected function getFailFerryMock() {
+               $mock = $this->getMockBuilder( ResourceLoaderTestModule::class )
+                       ->setMethods( [ 'getScript' ] )
+                       ->getMock();
+               $mock->method( 'getScript' )->will( $this->throwException(
+                       new Exception( 'Ferry not found' )
+               ) );
+               return $mock;
+       }
+
+       protected function getSimpleModuleMock( $script = '' ) {
+               $mock = $this->getMockBuilder( ResourceLoaderTestModule::class )
+                       ->setMethods( [ 'getScript' ] )
+                       ->getMock();
+               $mock->method( 'getScript' )->willReturn( $script );
+               return $mock;
+       }
+
+       /**
+        * @covers ResourceLoader::getCombinedVersion
+        */
+       public function testGetCombinedVersion() {
+               $rl = new EmptyResourceLoader();
+               $rl->register( [
+                       'foo' => self::getSimpleModuleMock(),
+                       'ferry' => self::getFailFerryMock(),
+                       'bar' => self::getSimpleModuleMock(),
+               ] );
+               $context = $this->getResourceLoaderContext( [], $rl );
+
+               $this->assertEquals(
+                       ResourceLoader::makeHash( self::BLANK_VERSION ),
+                       $rl->getCombinedVersion( $context, [ 'foo' ] ),
+                       'compute foo'
+               );
+
+               // Verify that getCombinedVersion() does not throw when ferry fails.
+               // Instead it gracefully continues to combine the remaining modules.
+               $this->assertEquals(
+                       ResourceLoader::makeHash( self::BLANK_VERSION . self::BLANK_VERSION ),
+                       $rl->getCombinedVersion( $context, [ 'foo', 'ferry', 'bar' ] ),
+                       'compute foo+ferry+bar (T152266)'
+               );
+       }
+
+       /**
+        * Verify that when building module content in a load.php response,
+        * an exception from one module will not break script output from
+        * other modules.
+        */
+       public function testMakeModuleResponseError() {
+               $modules = [
+                       'foo' => self::getSimpleModuleMock( 'foo();' ),
+                       'ferry' => self::getFailFerryMock(),
+                       'bar' => self::getSimpleModuleMock( 'bar();' ),
+               ];
+               $rl = new EmptyResourceLoader();
+               $rl->register( $modules );
+               $context = $this->getResourceLoaderContext(
+                       [
+                               'modules' => 'foo|ferry|bar',
+                               'only' => 'scripts',
+                       ],
+                       $rl
+               );
+
+               $response = $rl->makeModuleResponse( $context, $modules );
+               $errors = $rl->getErrors();
+
+               $this->assertCount( 1, $errors );
+               $this->assertRegExp( '/Ferry not found/', $errors[0] );
+               $this->assertEquals(
+                       'foo();bar();mw.loader.state( {
+    "ferry": "error",
+    "foo": "ready",
+    "bar": "ready"
+} );',
+                       $response
+               );
+       }
+
+       /**
+        * Verify that when building the startup module response,
+        * an exception from one module class will not break the entire
+        * startup module response. See T152266.
+        */
+       public function testMakeModuleResponseStartupError() {
+               $rl = new EmptyResourceLoader();
+               $rl->register( [
+                       'foo' => self::getSimpleModuleMock( 'foo();' ),
+                       'ferry' => self::getFailFerryMock(),
+                       'bar' => self::getSimpleModuleMock( 'bar();' ),
+                       'startup' => [ 'class' => 'ResourceLoaderStartUpModule' ],
+               ] );
+               $context = $this->getResourceLoaderContext(
+                       [
+                               'modules' => 'startup',
+                               'only' => 'scripts',
+                       ],
+                       $rl
+               );
+
+               $this->assertEquals(
+                       [ 'foo', 'ferry', 'bar', 'startup' ],
+                       $rl->getModuleNames(),
+                       'getModuleNames'
+               );
+
+               $modules = [ 'startup' => $rl->getModule( 'startup' ) ];
+               $response = $rl->makeModuleResponse( $context, $modules );
+               $errors = $rl->getErrors();
+
+               $this->assertRegExp( '/Ferry not found/', $errors[0] );
+               $this->assertCount( 1, $errors );
+               $this->assertRegExp(
+                       '/isCompatible.*function startUp/s',
+                       $response,
+                       'startup response undisrupted (T152266)'
+               );
+               $this->assertRegExp(
+                       '/register\([^)]+"ferry",\s*""/s',
+                       $response,
+                       'startup response registers broken module'
+               );
+               $this->assertRegExp(
+                       '/state\([^)]+"ferry":\s*"error"/s',
+                       $response,
+                       'startup response sets state to error'
+               );
+       }
 }
index cd84d79..ab3ac55 100644 (file)
@@ -33,7 +33,7 @@ class SpecialEditWatchlistTest extends SpecialPageTestBase {
                $user = new TestUser( __METHOD__ );
                list( $html, ) = $this->executeSpecialPage( 'clear', null, 'qqx', $user->getUser() );
                $this->assertRegExp(
-                       '/<form action=".*?Special:EditWatchlist\/clear" method="post" class="visualClear">/',
+                       '/<form class="mw-htmlform" action=".*?Special:EditWatchlist\/clear" method="post">/',
                        $html
                );
        }
index c11e6a3..ab92aee 100644 (file)
@@ -393,4 +393,136 @@ class SpecialRecentchangesTest extends MediaWikiTestCase {
                        $user
                );
        }
+
+       public function testFilterUserExpLevel() {
+               $this->setMwGlobals( [
+                       'wgLearnerEdits' => 10,
+                       'wgLearnerMemberSince' => 4,
+                       'wgExperiencedUserEdits' => 500,
+                       'wgExperiencedUserMemberSince' => 30,
+               ] );
+
+               $this->createUsers( [
+                       'Newcomer1' => [ 'edits' => 2, 'days' => 2 ],
+                       'Newcomer2' => [ 'edits' => 12, 'days' => 3 ],
+                       'Newcomer3' => [ 'edits' => 8, 'days' => 5 ],
+                       'Learner1' => [ 'edits' => 15, 'days' => 10 ],
+                       'Learner2' => [ 'edits' => 450, 'days' => 20 ],
+                       'Learner3' => [ 'edits' => 460, 'days' => 33 ],
+                       'Learner4' => [ 'edits' => 525, 'days' => 28 ],
+                       'Experienced1' => [ 'edits' => 538, 'days' => 33 ],
+               ] );
+
+               // newcomers only
+               $this->assertArrayEquals(
+                       [ 'Newcomer1', 'Newcomer2', 'Newcomer3' ],
+                       $this->fetchUsers( [ 'userExpLevel' => 'newcomer' ] )
+               );
+
+               // newcomers and learner
+               $this->assertArrayEquals(
+                       [
+                               'Newcomer1', 'Newcomer2', 'Newcomer3',
+                               'Learner1', 'Learner2', 'Learner3', 'Learner4',
+                       ],
+                       $this->fetchUsers( [ 'userExpLevel' => 'newcomer,learner' ] )
+               );
+
+               // newcomers and more learner
+               $this->assertArrayEquals(
+                       [
+                               'Newcomer1', 'Newcomer2', 'Newcomer3',
+                               'Experienced1',
+                       ],
+                       $this->fetchUsers( [ 'userExpLevel' => 'newcomer,experienced' ] )
+               );
+
+               // learner only
+               $this->assertArrayEquals(
+                       [ 'Learner1', 'Learner2', 'Learner3', 'Learner4' ],
+                       $this->fetchUsers( [ 'userExpLevel' => 'learner' ] )
+               );
+
+               // more experienced only
+               $this->assertArrayEquals(
+                       [ 'Experienced1' ],
+                       $this->fetchUsers( [ 'userExpLevel' => 'experienced' ] )
+               );
+
+               // learner and more experienced
+               $this->assertArrayEquals(
+                       [
+                               'Learner1', 'Learner2', 'Learner3', 'Learner4',
+                               'Experienced1',
+                       ],
+                       $this->fetchUsers( [ 'userExpLevel' => 'learner,experienced' ] )
+               );
+
+               // newcomers, learner, and more experienced
+               $this->assertArrayEquals(
+                       [
+                               'Newcomer1', 'Newcomer2', 'Newcomer3',
+                               'Learner1', 'Learner2', 'Learner3', 'Learner4',
+                               'Experienced1',
+                       ],
+                       $this->fetchUsers( [ 'userExpLevel' => 'newcomer,learner,experienced' ] )
+               );
+
+               // 'all'
+               $this->assertArrayEquals(
+                       [
+                               'Newcomer1', 'Newcomer2', 'Newcomer3',
+                               'Learner1', 'Learner2', 'Learner3', 'Learner4',
+                               'Experienced1',
+                       ],
+                       $this->fetchUsers( [ 'userExpLevel' => 'all' ] )
+               );
+       }
+
+       private function createUsers( $specs ) {
+               $dbw = wfGetDB( DB_MASTER );
+               foreach ( $specs as $name => $spec ) {
+                       User::createNew(
+                               $name,
+                               [
+                                       'editcount' => $spec['edits'],
+                                       'registration' => $dbw->timestamp( $this->daysAgo( $spec['days'] ) ),
+                                       'email' => 'ut',
+                               ]
+                       );
+               }
+       }
+
+       private function fetchUsers( $filters ) {
+               $specialRC = new SpecialRecentChanges();
+
+               $tables = [];
+               $conds = [];
+               $join_conds = [];
+
+               $specialRC->filterOnUserExperienceLevel(
+                       $tables,
+                       $conds,
+                       $join_conds,
+                       $filters
+               );
+
+               $result = wfGetDB( DB_MASTER )->select(
+                       'user',
+                       'user_name',
+                       array_filter( $conds ) + [ 'user_email' => 'ut' ]
+               );
+
+               $usernames = [];
+               foreach ( $result as $row ) {
+                       $usernames[] = $row->user_name;
+               }
+
+               return $usernames;
+       }
+
+       private function daysAgo( $days ) {
+               $secondsPerDay = 86400;
+               return time() - $days * $secondsPerDay;
+       }
 }
index 0819bf2..5d9cda7 100644 (file)
@@ -603,10 +603,10 @@ class UserTest extends MediaWikiTestCase {
                $user1tmp = $this->getTestUser()->getUser();
                $request1 = new FauxRequest();
                $request1->getSession()->setUser( $user1tmp );
-               $expiryFiveDays = time() + ( 5 * 24 * 60 * 60 );
+               $expiryFiveHours = wfTimestamp() + ( 5 * 60 * 60 );
                $block = new Block( [
                        'enableAutoblock' => true,
-                       'expiry' => wfTimestamp( TS_MW, $expiryFiveDays ),
+                       'expiry' => wfTimestamp( TS_MW, $expiryFiveHours ),
                ] );
                $block->setTarget( $user1tmp );
                $block->insert();
@@ -625,7 +625,7 @@ class UserTest extends MediaWikiTestCase {
                $cookies = $request1->response()->getCookies();
                $this->assertArrayHasKey( 'wmsitetitleBlockID', $cookies );
                $this->assertEquals( $block->getId(), $cookies['wmsitetitleBlockID']['value'] );
-               $this->assertEquals( $expiryFiveDays, $cookies['wmsitetitleBlockID']['expire'] );
+               $this->assertEquals( $expiryFiveHours, $cookies['wmsitetitleBlockID']['expire'] );
 
                // 2. Create a new request, set the cookies, and see if the (anon) user is blocked.
                $request2 = new FauxRequest();
@@ -696,14 +696,12 @@ class UserTest extends MediaWikiTestCase {
 
        /**
         * When a user is autoblocked and a cookie is set to track them, the expiry time of the cookie
-        * should match the block's expiry. If the block is infinite, the cookie expiry time should
-        * match $wgCookieExpiration. If the expiry time is changed, the cookie's should change with it.
+        * should match the block's expiry, to a maximum of 24 hours. If the expiry time is changed,
+        * the cookie's should change with it.
         */
        public function testAutoblockCookieInfiniteExpiry() {
-               $cookieExpiration = 20 * 24 * 60 * 60; // 20 days
                $this->setMwGlobals( [
                        'wgCookieSetOnAutoblock' => true,
-                       'wgCookieExpiration' => $cookieExpiration,
                        'wgCookiePrefix' => 'wm_infinite_block',
                ] );
                // 1. Log in a test user, and block them indefinitely.
@@ -724,12 +722,21 @@ class UserTest extends MediaWikiTestCase {
                $this->assertTrue( $block->isAutoblocking() );
                $this->assertGreaterThanOrEqual( 1, $user1->getBlockId() );
                $cookies = $request1->response()->getCookies();
-               // Calculate the expected cookie expiry date.
+               // Test the cookie's expiry to the nearest minute.
                $this->assertArrayHasKey( 'wm_infinite_blockBlockID', $cookies );
-               $this->assertEquals( time() + $cookieExpiration, $cookies['wm_infinite_blockBlockID']['expire'] );
+               $expOneDay = wfTimestamp() + ( 24 * 60 * 60 );
+               // Check for expiry dates in a 10-second window, to account for slow testing.
+               $this->assertGreaterThan(
+                       $expOneDay - 5,
+                       $cookies['wm_infinite_blockBlockID']['expire']
+               );
+               $this->assertLessThan(
+                       $expOneDay + 5,
+                       $cookies['wm_infinite_blockBlockID']['expire']
+               );
 
-               // 3. Change the block's expiry (to 2 days), and the cookie's should be changed also.
-               $newExpiry = time() + 2 * 24 * 60 * 60;
+               // 3. Change the block's expiry (to 2 hours), and the cookie's should be changed also.
+               $newExpiry = wfTimestamp() + 2 * 60 * 60;
                $block->mExpiry = wfTimestamp( TS_MW, $newExpiry );
                $block->update();
                $user2tmp = $this->getTestUser()->getUser();
@@ -739,6 +746,7 @@ class UserTest extends MediaWikiTestCase {
                $user2->mBlock = $block;
                $user2->load();
                $cookies = $request2->response()->getCookies();
+               $this->assertEquals( wfTimestamp( TS_MW, $newExpiry ), $block->getExpiry() );
                $this->assertEquals( $newExpiry, $cookies['wm_infinite_blockBlockID']['expire'] );
 
                // Clean up.
index 771cda5..c1b774a 100644 (file)
@@ -5,7 +5,7 @@
  * @file
  */
 
-/** Tests for MediaWiki languages/classes/LanguageHe.php */
+/** Tests for MediaWiki Hebrew grammar transformation handling */
 class LanguageHeTest extends LanguageClassesTestCase {
        /**
         * The most common usage for the plural forms is two forms,
index 3a959a3..6a00ac9 100644 (file)
@@ -44,7 +44,7 @@
                } );
        } );
 
-       QUnit.test( 'API error', function ( assert ) {
+       QUnit.test( 'API error errorformat=bc', function ( assert ) {
                var api = new mw.Api();
 
                this.server.respond( [ 200, { 'Content-Type': 'application/json' },
                        .always( assert.async() );
        } );
 
+       QUnit.test( 'API error errorformat!=bc', function ( assert ) {
+               var api = new mw.Api();
+
+               this.server.respond( [ 200, { 'Content-Type': 'application/json' },
+                       '{ "errors": [ { "code": "unknown_action", "key": "unknown-error", "params": [] } ] }'
+               ] );
+
+               api.get( { action: 'doesntexist' } )
+                       .fail( function ( errorCode ) {
+                               assert.equal( errorCode, 'unknown_action', 'API error should reject the deferred' );
+                       } )
+                       .always( assert.async() );
+       } );
+
        QUnit.test( 'FormData support', function ( assert ) {
                var api = new mw.Api();
 
index b2fac3c..2171f34 100644 (file)
@@ -3,11 +3,11 @@
 
        QUnit.module( 'mediawiki.language', QUnit.newMwEnvironment( {
                setup: function () {
-                       this.liveLangData = mw.language.data.values;
-                       mw.language.data.values = $.extend( true, {}, this.liveLangData );
+                       this.liveLangData = mw.language.data;
+                       mw.language.data = {};
                },
                teardown: function () {
-                       mw.language.data.values = this.liveLangData;
+                       mw.language.data = this.liveLangData;
                },
                messages: {
                        // mw.language.listToText test
index 045b633..e6e798b 100644 (file)
                        // MeeGo
                        'Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13',
                        // UC Mini (speed mode on)
-                       'Mozilla/5.0 (X11; U; Linux i686; zh-CN; r:1.2.3.4) Gecko/'
+                       'Mozilla/5.0 (X11; U; Linux i686; zh-CN; r:1.2.3.4) Gecko/',
+                       // Google Web Light proxy
+                       'Mozilla/5.0 (Linux; Android 4.2.1; en-us; Nexus 5 Build/JOP40D) AppleWebKit/535.19 (KHTML, like Gecko; googleweblight) Chrome/38.0.1025.166 Mobile Safari/535.19'
                ]
        };