Merge "filebackend: rename and simplify header sanitizing methods in SwiftFileBackend"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Sat, 14 Sep 2019 00:12:05 +0000 (00:12 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Sat, 14 Sep 2019 00:12:05 +0000 (00:12 +0000)
487 files changed:
.phpcs.xml
CODE_OF_CONDUCT.md
RELEASE-NOTES-1.34
api.php
autoload.php
composer.json
docs/extension.schema.v1.json
docs/extension.schema.v2.json
docs/hooks.txt
img_auth.php
includes/ActorMigration.php
includes/AjaxResponse.php
includes/DefaultSettings.php
includes/MovePage.php
includes/OutputPage.php
includes/PHPVersionCheck.php
includes/ProtectionForm.php
includes/Revision.php
includes/Revision/RevisionRecord.php
includes/Revision/RevisionStore.php
includes/ServiceWiring.php
includes/Setup.php
includes/Storage/DerivedPageDataUpdater.php
includes/StreamFile.php
includes/Title.php
includes/actions/HistoryAction.php
includes/actions/InfoAction.php
includes/actions/RawAction.php
includes/api/ApiEditPage.php
includes/api/ApiMain.php
includes/api/ApiModuleManager.php
includes/api/ApiPageSet.php
includes/api/ApiQuery.php
includes/api/ApiQueryAllDeletedRevisions.php
includes/api/ApiQueryAllRevisions.php
includes/api/ApiQueryAllUsers.php
includes/api/ApiQueryContributors.php
includes/api/ApiQueryDeletedRevisions.php
includes/api/ApiQueryFilearchive.php
includes/api/ApiQueryRevisions.php
includes/api/ApiQueryStashImageInfo.php
includes/api/ApiQueryUserContribs.php
includes/api/ApiQueryUserInfo.php
includes/api/ApiResetPassword.php
includes/api/ApiRevisionDelete.php
includes/api/ApiSetNotificationTimestamp.php
includes/api/ApiTag.php
includes/api/i18n/ar.json
includes/api/i18n/en.json
includes/api/i18n/fr.json
includes/api/i18n/it.json
includes/api/i18n/ko.json
includes/api/i18n/mk.json
includes/api/i18n/pl.json
includes/api/i18n/pt-br.json
includes/api/i18n/qqq.json
includes/api/i18n/ru.json
includes/api/i18n/zh-hant.json
includes/auth/AuthenticationRequest.php
includes/auth/ResetPasswordSecondaryAuthenticationProvider.php
includes/block/BlockManager.php
includes/block/DatabaseBlock.php
includes/cache/LinkCache.php
includes/cache/UserCache.php
includes/cache/localisation/LCStoreDB.php
includes/changes/CategoryMembershipChange.php
includes/changes/RCCacheEntryFactory.php
includes/changes/RecentChange.php
includes/changetags/ChangeTags.php
includes/clientpool/SquidPurgeClient.php
includes/composer/ComposerPhpunitXmlCoverageEdit.php [new file with mode: 0644]
includes/context/RequestContext.php
includes/dao/DBAccessBase.php
includes/debug/logger/ConsoleLogger.php
includes/deferred/CdnCacheUpdate.php
includes/deferred/HTMLCacheUpdate.php
includes/deferred/LinksUpdate.php
includes/deferred/SearchUpdate.php
includes/diff/DifferenceEngine.php
includes/export/DumpMultiWriter.php
includes/export/WikiExporter.php
includes/externalstore/ExternalStoreDB.php
includes/filerepo/file/ArchivedFile.php
includes/filerepo/file/File.php
includes/filerepo/file/LocalFile.php
includes/filerepo/file/LocalFileDeleteBatch.php
includes/filerepo/file/LocalFileMoveBatch.php
includes/filerepo/file/OldLocalFile.php
includes/gallery/ImageGalleryBase.php
includes/import/ImportStreamSource.php
includes/import/ImportStringSource.php
includes/installer/CliInstaller.php
includes/installer/DatabaseUpdater.php
includes/installer/Installer.php
includes/installer/MysqlUpdater.php
includes/installer/PostgresUpdater.php
includes/installer/SqliteUpdater.php
includes/installer/WebInstallerOptions.php
includes/installer/i18n/ckb.json
includes/installer/i18n/fr.json
includes/installer/i18n/ia.json
includes/installer/i18n/it.json
includes/installer/i18n/ja.json
includes/installer/i18n/nl.json
includes/installer/i18n/pl.json
includes/jobqueue/jobs/RefreshLinksJob.php
includes/libs/MemoizedCallable.php
includes/libs/composer/ComposerInstalled.php
includes/libs/composer/ComposerJson.php
includes/libs/composer/ComposerLock.php
includes/libs/filebackend/FSFileBackend.php
includes/libs/filebackend/FileBackendStore.php
includes/libs/filebackend/MemoryFileBackend.php
includes/libs/filebackend/SwiftFileBackend.php
includes/libs/filebackend/fileophandle/FileBackendStoreOpHandle.php
includes/libs/filebackend/fsfile/FSFile.php
includes/libs/lockmanager/QuorumLockManager.php
includes/libs/mime/XmlTypeCheck.php
includes/libs/objectcache/MultiWriteBagOStuff.php
includes/libs/objectcache/ReplicatedBagOStuff.php
includes/libs/rdbms/lbfactory/LBFactoryMulti.php
includes/libs/redis/RedisConnectionPool.php
includes/logging/BlockLogFormatter.php
includes/logging/ContentModelLogFormatter.php
includes/logging/DeleteLogFormatter.php
includes/logging/LogEventsList.php
includes/logging/LogFormatter.php
includes/logging/LogPager.php
includes/logging/ManualLogEntry.php
includes/logging/MergeLogFormatter.php
includes/logging/MoveLogFormatter.php
includes/logging/ProtectLogFormatter.php
includes/mail/EmailNotification.php
includes/mail/UserMailer.php
includes/media/JpegMetadataExtractor.php
includes/page/Article.php
includes/page/ImageHistoryList.php
includes/page/ImagePage.php
includes/page/WikiPage.php
includes/parser/PPDPart.php
includes/parser/PPDStack.php
includes/parser/PPDStackElement.php
includes/parser/PPFrame.php
includes/parser/PPFrame_DOM.php
includes/parser/PPTemplateFrame_Hash.php
includes/parser/Preprocessor.php
includes/parser/Preprocessor_Hash.php
includes/preferences/DefaultPreferencesFactory.php
includes/resourceloader/ResourceLoader.php
includes/resourceloader/ResourceLoaderClientHtml.php
includes/resourceloader/ResourceLoaderLanguageDataModule.php
includes/resourceloader/ResourceLoaderUserDefaultsModule.php
includes/resourceloader/ResourceLoaderUserOptionsModule.php
includes/resourceloader/ResourceLoaderUserTokensModule.php
includes/revisiondelete/RevDelList.php
includes/revisiondelete/RevisionDeleteUser.php
includes/session/SessionManager.php
includes/session/SessionOverflowException.php [new file with mode: 0644]
includes/skins/SkinTemplate.php
includes/specialpage/LoginSignupSpecialPage.php
includes/specialpage/QueryPage.php
includes/specialpage/SpecialPage.php
includes/specialpage/SpecialPageFactory.php
includes/specials/SpecialAncientPages.php [new file with mode: 0644]
includes/specials/SpecialAncientpages.php [deleted file]
includes/specials/SpecialApiSandbox.php
includes/specials/SpecialAutoblockList.php
includes/specials/SpecialBlock.php
includes/specials/SpecialBlockList.php
includes/specials/SpecialBrokenRedirects.php
includes/specials/SpecialChangeContentModel.php
includes/specials/SpecialChangeEmail.php
includes/specials/SpecialConfirmEmail.php [new file with mode: 0644]
includes/specials/SpecialConfirmemail.php [deleted file]
includes/specials/SpecialContributions.php
includes/specials/SpecialCreateAccount.php
includes/specials/SpecialDeadendPages.php [new file with mode: 0644]
includes/specials/SpecialDeadendpages.php [deleted file]
includes/specials/SpecialDeletedContributions.php
includes/specials/SpecialDoubleRedirects.php
includes/specials/SpecialEditTags.php
includes/specials/SpecialEmailInvalidate.php
includes/specials/SpecialEmailUser.php
includes/specials/SpecialExpandTemplates.php
includes/specials/SpecialExport.php
includes/specials/SpecialFewestRevisions.php [new file with mode: 0644]
includes/specials/SpecialFewestrevisions.php [deleted file]
includes/specials/SpecialFileDuplicateSearch.php
includes/specials/SpecialImport.php
includes/specials/SpecialLinkSearch.php
includes/specials/SpecialListDuplicatedFiles.php
includes/specials/SpecialListRedirects.php [new file with mode: 0644]
includes/specials/SpecialListredirects.php [deleted file]
includes/specials/SpecialLog.php
includes/specials/SpecialLonelyPages.php [new file with mode: 0644]
includes/specials/SpecialLonelypages.php [deleted file]
includes/specials/SpecialLongPages.php [new file with mode: 0644]
includes/specials/SpecialLongpages.php [deleted file]
includes/specials/SpecialMIMESearch.php [new file with mode: 0644]
includes/specials/SpecialMIMEsearch.php [deleted file]
includes/specials/SpecialMediaStatistics.php
includes/specials/SpecialMostCategories.php [new file with mode: 0644]
includes/specials/SpecialMostInterwikis.php [new file with mode: 0644]
includes/specials/SpecialMostLinked.php [new file with mode: 0644]
includes/specials/SpecialMostLinkedCategories.php [new file with mode: 0644]
includes/specials/SpecialMostLinkedTemplates.php [new file with mode: 0644]
includes/specials/SpecialMostRevisions.php [new file with mode: 0644]
includes/specials/SpecialMostcategories.php [deleted file]
includes/specials/SpecialMostinterwikis.php [deleted file]
includes/specials/SpecialMostlinked.php [deleted file]
includes/specials/SpecialMostlinkedcategories.php [deleted file]
includes/specials/SpecialMostlinkedtemplates.php [deleted file]
includes/specials/SpecialMostrevisions.php [deleted file]
includes/specials/SpecialMovepage.php
includes/specials/SpecialNewFiles.php [new file with mode: 0644]
includes/specials/SpecialNewimages.php [deleted file]
includes/specials/SpecialPageData.php
includes/specials/SpecialPagesWithProp.php
includes/specials/SpecialPasswordReset.php
includes/specials/SpecialPreferences.php
includes/specials/SpecialRecentChanges.php
includes/specials/SpecialRecentChangesLinked.php
includes/specials/SpecialRedirect.php
includes/specials/SpecialRevisionDelete.php
includes/specials/SpecialRunJobs.php
includes/specials/SpecialShortPages.php [new file with mode: 0644]
includes/specials/SpecialShortpages.php [deleted file]
includes/specials/SpecialTags.php
includes/specials/SpecialUnblock.php
includes/specials/SpecialUncategorizedCategories.php [new file with mode: 0644]
includes/specials/SpecialUncategorizedImages.php [new file with mode: 0644]
includes/specials/SpecialUncategorizedPages.php [new file with mode: 0644]
includes/specials/SpecialUncategorizedTemplates.php [new file with mode: 0644]
includes/specials/SpecialUncategorizedcategories.php [deleted file]
includes/specials/SpecialUncategorizedimages.php [deleted file]
includes/specials/SpecialUncategorizedpages.php [deleted file]
includes/specials/SpecialUncategorizedtemplates.php [deleted file]
includes/specials/SpecialUndelete.php
includes/specials/SpecialUnusedCategories.php [new file with mode: 0644]
includes/specials/SpecialUnusedImages.php [new file with mode: 0644]
includes/specials/SpecialUnusedTemplates.php [new file with mode: 0644]
includes/specials/SpecialUnusedcategories.php [deleted file]
includes/specials/SpecialUnusedimages.php [deleted file]
includes/specials/SpecialUnusedtemplates.php [deleted file]
includes/specials/SpecialUnwatchedPages.php [new file with mode: 0644]
includes/specials/SpecialUnwatchedpages.php [deleted file]
includes/specials/SpecialUpload.php
includes/specials/SpecialUserrights.php
includes/specials/SpecialWantedCategories.php [new file with mode: 0644]
includes/specials/SpecialWantedTemplates.php [new file with mode: 0644]
includes/specials/SpecialWantedcategories.php [deleted file]
includes/specials/SpecialWantedtemplates.php [deleted file]
includes/specials/SpecialWatchlist.php
includes/specials/SpecialWhatLinksHere.php
includes/specials/SpecialWithoutInterwiki.php [new file with mode: 0644]
includes/specials/SpecialWithoutinterwiki.php [deleted file]
includes/specials/forms/PreferencesFormOOUI.php
includes/specials/forms/UploadForm.php
includes/specials/pagers/ActiveUsersPager.php
includes/specials/pagers/AllMessagesTablePager.php
includes/specials/pagers/BlockListPager.php
includes/specials/pagers/ContribsPager.php
includes/specials/pagers/DeletedContribsPager.php
includes/specials/pagers/MergeHistoryPager.php
includes/specials/pagers/NewFilesPager.php
includes/specials/pagers/ProtectedPagesPager.php
includes/specials/pagers/ProtectedTitlesPager.php
includes/specials/pagers/UsersPager.php
includes/upload/UploadBase.php
includes/upload/UploadFromUrl.php
includes/user/LocalIdLookup.php
includes/user/PasswordReset.php
includes/user/User.php
includes/user/UserNamePrefixSearch.php
includes/widget/CheckMatrixWidget.php
includes/widget/ComplexTitleInputWidget.php
includes/widget/NamespaceInputWidget.php
includes/widget/SelectWithInputWidget.php
includes/widget/SizeFilterWidget.php
includes/widget/TagMultiselectWidget.php
index.php
jsduck.json
languages/i18n/ar.json
languages/i18n/ast.json
languages/i18n/ban.json
languages/i18n/bg.json
languages/i18n/bn.json
languages/i18n/ckb.json
languages/i18n/cs.json
languages/i18n/diq.json
languages/i18n/dtp.json
languages/i18n/dty.json
languages/i18n/en.json
languages/i18n/exif/id.json
languages/i18n/exif/nb.json
languages/i18n/exif/pl.json
languages/i18n/exif/sd.json
languages/i18n/fi.json
languages/i18n/fr.json
languages/i18n/gl.json
languages/i18n/gom-deva.json
languages/i18n/gom-latn.json
languages/i18n/he.json
languages/i18n/hr.json
languages/i18n/hu.json
languages/i18n/ia.json
languages/i18n/id.json
languages/i18n/io.json
languages/i18n/ja.json
languages/i18n/jv.json
languages/i18n/ka.json
languages/i18n/khw.json
languages/i18n/ko.json
languages/i18n/luz.json
languages/i18n/lv.json
languages/i18n/min.json
languages/i18n/mk.json
languages/i18n/mni.json
languages/i18n/my.json
languages/i18n/nap.json
languages/i18n/nb.json
languages/i18n/nds-nl.json
languages/i18n/ne.json
languages/i18n/nl.json
languages/i18n/nqo.json
languages/i18n/pl.json
languages/i18n/pt-br.json
languages/i18n/qqq.json
languages/i18n/roa-tara.json
languages/i18n/ru.json
languages/i18n/sd.json
languages/i18n/sh.json
languages/i18n/sk.json
languages/i18n/sl.json
languages/i18n/sv.json
languages/i18n/szl.json
languages/i18n/te.json
languages/i18n/tr.json
languages/i18n/tt-cyrl.json
languages/i18n/uk.json
languages/i18n/zgh.json
languages/i18n/zh-hant.json
languages/messages/MessagesHyw.php
load.php
maintenance/Maintenance.php
maintenance/archives/patch-drop-user-fields.sql [new file with mode: 0644]
maintenance/cleanupImages.php
maintenance/cleanupTitles.php
maintenance/compareParsers.php
maintenance/dumpIterator.php
maintenance/getReplicaServer.php
maintenance/importDump.php
maintenance/includes/BackupDumper.php
maintenance/includes/MigrateActors.php
maintenance/install.php
maintenance/mwdocgen.php
maintenance/postgres/tables.sql
maintenance/preprocessDump.php
maintenance/preprocessorFuzzTest.php
maintenance/reassignEdits.php
maintenance/rebuildImages.php
maintenance/recountCategories.php
maintenance/removeUnusedAccounts.php
maintenance/renderDump.php
maintenance/sqlite/archives/patch-archive-drop-ar_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-filearchive-drop-fa_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-image-drop-img_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-ipblocks-drop-ipb_by.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-logging-drop-log_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-oldimage-drop-oi_user.sql [new file with mode: 0644]
maintenance/sqlite/archives/patch-recentchanges-drop-rc_user.sql [new file with mode: 0644]
maintenance/storage/blobs.sql
maintenance/storage/checkStorage.php
maintenance/storage/recompressTracked.php
maintenance/tables.sql
maintenance/userOptions.php
opensearch_desc.php
profileinfo.php
resources/Resources.php
resources/lib/foreign-resources.yaml
resources/lib/ooui/History.md
resources/lib/ooui/i18n/fr.json
resources/lib/ooui/i18n/pl.json
resources/lib/ooui/oojs-ui-apex.js
resources/lib/ooui/oojs-ui-core-apex.css
resources/lib/ooui/oojs-ui-core-wikimediaui.css
resources/lib/ooui/oojs-ui-core.js
resources/lib/ooui/oojs-ui-toolbars-apex.css
resources/lib/ooui/oojs-ui-toolbars-wikimediaui.css
resources/lib/ooui/oojs-ui-toolbars.js
resources/lib/ooui/oojs-ui-widgets-apex.css
resources/lib/ooui/oojs-ui-widgets-wikimediaui.css
resources/lib/ooui/oojs-ui-widgets.js
resources/lib/ooui/oojs-ui-wikimediaui.js
resources/lib/ooui/oojs-ui-windows-apex.css
resources/lib/ooui/oojs-ui-windows-wikimediaui.css
resources/lib/ooui/oojs-ui-windows.js
resources/lib/ooui/themes/apex/icons-editing-advanced.json
resources/lib/ooui/themes/apex/icons-user.json
resources/lib/ooui/themes/wikimediaui/icons-editing-advanced.json
resources/lib/ooui/themes/wikimediaui/icons-user.json
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.png [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.svg [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.png [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.svg [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker.png [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/beaker.svg [deleted file]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userAvatarOutline-invert.svg
resources/lib/ooui/themes/wikimediaui/images/icons/userAvatarOutline-progressive.svg
resources/lib/ooui/themes/wikimediaui/images/icons/userAvatarOutline.svg
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.svg [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.png [new file with mode: 0644]
resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.svg [new file with mode: 0644]
resources/src/jquery.color/jquery.color.js [new file with mode: 0644]
resources/src/jquery.color/jquery.colorUtil.js [new file with mode: 0644]
resources/src/jquery/jquery.color.js [deleted file]
resources/src/jquery/jquery.colorUtil.js [deleted file]
resources/src/mediawiki.ForeignApi.core.js
resources/src/mediawiki.RegExp.js [deleted file]
resources/src/mediawiki.Title/Title.js
resources/src/mediawiki.Title/phpCharToUpper.json
resources/src/mediawiki.htmlform.checker.js
resources/src/mediawiki.legacy/shared.css
resources/src/mediawiki.util/util.js
rest.php
tests/parser/ParserTestRunner.php
tests/phpunit/MediaWikiIntegrationTestCase.php
tests/phpunit/data/media/jpeg-xmp-nullchar.jpg [new file with mode: 0644]
tests/phpunit/includes/ActorMigrationTest.php
tests/phpunit/includes/ActorMigrationTest.sql [new file with mode: 0644]
tests/phpunit/includes/Revision/RenderedRevisionTest.php
tests/phpunit/includes/Revision/RevisionQueryInfoTest.php
tests/phpunit/includes/Revision/RevisionStoreDbTestBase.php
tests/phpunit/includes/RevisionDbTestBase.php
tests/phpunit/includes/RevisionTest.php
tests/phpunit/includes/TitleTest.php
tests/phpunit/includes/api/ApiDeleteTest.php
tests/phpunit/includes/api/ApiMainTest.php
tests/phpunit/includes/api/ApiModuleManagerTest.php
tests/phpunit/includes/api/ApiPageSetTest.php
tests/phpunit/includes/api/ApiQueryLanguageinfoTest.php
tests/phpunit/includes/api/ApiRevisionDeleteTest.php
tests/phpunit/includes/api/format/ApiFormatBaseTest.php
tests/phpunit/includes/api/format/ApiFormatTestBase.php
tests/phpunit/includes/api/query/ApiQueryUserContribsTest.php
tests/phpunit/includes/block/BlockManagerTest.php
tests/phpunit/includes/deferred/LinksUpdateTest.php
tests/phpunit/includes/logging/DatabaseLogEntryTest.php
tests/phpunit/includes/media/JpegMetadataExtractorTest.php
tests/phpunit/includes/page/PageArchiveTestBase.php
tests/phpunit/includes/preferences/DefaultPreferencesFactoryTest.php
tests/phpunit/includes/session/SessionManagerTest.php
tests/phpunit/includes/specialpage/ChangesListSpecialPageTest.php
tests/phpunit/includes/specialpage/SpecialPageFactoryTest.php
tests/phpunit/includes/specials/QueryAllSpecialPagesTest.php
tests/phpunit/includes/specials/SpecialBlankPageTest.php
tests/phpunit/includes/specials/SpecialMIMESearchTest.php
tests/phpunit/includes/specials/SpecialShortPagesTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/SpecialShortpagesTest.php [deleted file]
tests/phpunit/includes/specials/SpecialUncategorizedCategoriesTest.php [new file with mode: 0644]
tests/phpunit/includes/specials/UncategorizedCategoriesPageTest.php [deleted file]
tests/phpunit/includes/user/LocalIdLookupTest.php
tests/phpunit/includes/user/PasswordResetTest.php
tests/phpunit/includes/user/UserGroupMembershipTest.php
tests/phpunit/includes/user/UserTest.php
tests/phpunit/maintenance/MWDoxygenFilterTest.php
tests/phpunit/maintenance/deleteAutoPatrolLogsTest.php
tests/qunit/QUnitTestResources.php
tests/qunit/suites/resources/mediawiki.api/mediawiki.ForeignApi.test.js
tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
thumb.php
thumb_handler.php

index 9f11ebc..f971881 100644 (file)
                        Whitelist existing violations, but enable the sniff to prevent
                        any new occurrences.
                -->
-               <exclude-pattern>*/includes/specials/SpecialMostinterwikis\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialAncientpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialBrokenRedirects\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialConfirmemail\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialDeadendpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialDeletedContributions\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialDoubleRedirects\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialEmailInvalidate\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialFewestrevisions\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialFileDuplicateSearch\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialLinkSearch\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialListDuplicatedFiles\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialListredirects\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialLonelypages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialLongpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMIMEsearch\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMediaStatistics\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostcategories\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialMostimages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostlinked\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostlinkedcategories\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostlinkedtemplates\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialMostrevisions\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialMovepage\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialNewimages\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialRandompage\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialShortpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUncategorizedcategories\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUncategorizedimages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUncategorizedpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUncategorizedtemplates\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUnusedcategories\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUnusedimages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUnusedtemplates\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialUnwatchedpages\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialUserrights\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialWantedcategories\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialWantedfiles\.php</exclude-pattern>
                <exclude-pattern>*/includes/specials/SpecialWantedpages\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialWantedtemplates\.php</exclude-pattern>
-               <exclude-pattern>*/includes/specials/SpecialWithoutinterwiki\.php</exclude-pattern>
                <exclude-pattern>*/maintenance/CodeCleanerGlobalsPass.inc</exclude-pattern>
                <exclude-pattern>*/maintenance/archives/upgradeLogging\.php</exclude-pattern>
                <exclude-pattern>*/maintenance/benchmarks/bench_HTTP_HTTPS\.php</exclude-pattern>
index 498acf7..3d9f26a 100644 (file)
@@ -1 +1,4 @@
+Code of Conduct
+===============
+
 The development of this software is covered by a [Code of Conduct](https://www.mediawiki.org/wiki/Special:MyLanguage/Code_of_Conduct).
index aaf4d78..d2dbce1 100644 (file)
@@ -80,6 +80,7 @@ $wgPasswordPolicy['policies']['default']['PasswordNotInLargeBlacklist'] = false;
 * $wgWikiDiff2MovedParagraphDetectionCutoff — If you still want a custom change
   size threshold, please specify in php.ini, using the configuration variable
   wikidiff2.moved_paragraph_detection_cutoff.
+* $wgUseESI - This experimental setting, deprecated in 1.33, is now removed.
 * $wgDebugPrintHttpHeaders - The default of including HTTP headers in the
   debug log channel is no longer configurable. The debug log itself remains
   configurable via $wgDebugLogFile.
@@ -90,6 +91,8 @@ $wgPasswordPolicy['policies']['default']['PasswordNotInLargeBlacklist'] = false;
 * $wgDBOracleDRCP - If you must use persistent connections, set DBO_PERSISTENT
   in the 'flags' field for servers in $wgDBServers (or $wgLBFactoryConf).
 * $wgMemCachedDebug - Set the cache "debug" field in $wgObjectCaches instead.
+* $wgActorTableSchemaMigrationStage has been removed. Extension code for
+  MediaWiki 1.31+ finding it unset should treat it as being SCHEMA_COMPAT_NEW.
 
 === New user-facing features in 1.34 ===
 * Special:Mute has been added as a quick way for users to block unwanted emails
@@ -117,6 +120,12 @@ $wgPasswordPolicy['policies']['default']['PasswordNotInLargeBlacklist'] = false;
   GetBlockedStatus.
 * ObjectFactory is available as a service. When used as a service, the object
   specs can now specify needed DI services.
+* (T222388) Special pages can now be specified as an ObjectFactory spec,
+  allowing the construction of special pages that require services to be
+  injected in their constructor.
+* (T222388) API modules can now be specified as an ObjectFactory spec,
+  allowing the construction of modules that require services to be injected
+  in their constructor.
 
 === External library changes in 1.34 ===
 
@@ -153,8 +162,15 @@ $wgPasswordPolicy['policies']['default']['PasswordNotInLargeBlacklist'] = false;
 === Action API changes in 1.34 ===
 * The 'recenteditcount' response property from action=query list=allusers,
   deprecated in 1.25, has been removed.
+* (T60993) action=query list=filearchive, list=alldeletedrevisions and
+  prop=deletedrevisions no longer require the 'deletedhistory' user right.
 
 === Action API internal changes in 1.34 ===
+* The exception thrown in ApiModuleManager::getModule has been changed
+  from an MWException to an UnexpectedValueException, thrown by ObjectFactory.
+  ApiModuleManager::getModule now also throws InvalidArgumentExceptions when
+  ObjectFactory is presented with an invalid spec or incorrectly constructed
+  objects.
 * …
 
 === Languages updated in 1.34 ===
@@ -174,6 +190,34 @@ because of Phabricator reports.
   * CryptRand class
   * CryptRand service
   * Functions of the MWCryptRand class: singleton(), wasStrong() and generate().
+* Various Special Page PHP Classes were renamed (mostly casing changes):
+  * SpecialAncientpages => SpecialAncientPages
+  * SpecialConfirmemail => SpecialConfirmEmail
+  * SpecialDeadendpages => SpecialDeadendPages
+  * SpecialFewestrevisions => SpecialFewestRevisions
+  * SpecialListredirects => SpecialListRedirects
+  * SpecialLonelypages => SpecialLonelyPages
+  * SpecialLongpages => SpecialLongPages
+  * SpecialMIMEsearch => SpecialMIMESearch
+  * SpecialMostcategories => SpecialMostCategories
+  * SpecialMostinterwikis => SpecialMostInterwikis
+  * SpecialMostlinked => SpecialMostLinked
+  * SpecialMostlinkedcategories => SpecialMostLinkedCategories
+  * SpecialMostlinkedtemplates => SpecialMostLinkedTemplates
+  * SpecialMostrevisions => SpecialMostRevisions
+  * SpecialNewimages => SpecialNewFiles
+  * SpecialShortpages => SpecialShortPages
+  * SpecialUncategorizedcategories => SpecialUncategorizedCategories
+  * SpecialUncategorizedimages => SpecialUncategorizedImages
+  * SpecialUncategorizedpages => SpecialUncategorizedPages
+  * SpecialUncategorizedtemplates => SpecialUncategorizedTemplates
+  * SpecialUnusedcategories => SpecialUnusedCategories
+  * SpecialUnusedimages => SpecialUnusedImages
+  * SpecialUnusedtemplates => SpecialUnusedTemplates
+  * SpecialUnwatchedpages => SpecialUnwatchedPages
+  * SpecialWantedcategories => SpecialWantedCategories
+  * SpecialWantedtemplates => SpecialWantedTemplates
+  * SpecialWithoutinterwiki => SpecialWithoutInterwiki
 * Language::setCode, deprecated in 1.32, was removed. Use Language::factory to
   create a new Language object with a different language code.
 * MWNamespace::clearCaches() has been removed.  So has the $rebuild parameter
@@ -258,6 +302,7 @@ because of Phabricator reports.
   Use the mediawiki.String module instead.
 * mw.language.specialCharacters, deprecated in 1.33, has been removed.
   Use require( 'mediawiki.language.specialCharacters' ) instead.
+* The jquery.colorUtil module was removed. Use jquery.color instead.
 * EditPage::submit(), deprecated in 1.29, has been removed. Use $this->edit()
   directly.
 * HTMLForm::getErrors(), deprecated in 1.28, has been removed. Use
@@ -371,7 +416,20 @@ because of Phabricator reports.
   should only be used to unblock a blocked user.
 * Parameters for index.php from PATH_INFO, such as the title, are no longer
   written to $_GET.
-* …
+* The selectFields() methods on classes LocalFile, ArchivedFile, OldLocalFile,
+  DatabaseBlock, and RecentChange, deprecated in 1.31, have been removed. Use
+  the corresponding getQueryInfo() methods instead.
+* The following methods on Revision, deprecated since 1.31, have been removed.
+  Use RevisionStore::getQueryInfo() or RevisionStore::getArchiveQueryInfo()
+  instead.
+  * Revision::userJoinCond()
+  * Revision::pageJoinCond()
+  * Revision::selectFields()
+  * Revision::selectArchiveFields()
+  * Revision::selectTextFields()
+  * Revision::selectPageFields()
+  * Revision::selectUserFields()
+* User::setNewpassword(), deprecated in 1.27 has been removed.
 
 === Deprecations in 1.34 ===
 * The MWNamespace class is deprecated. Use NamespaceInfo.
@@ -492,6 +550,21 @@ because of Phabricator reports.
   or extend RevisionSearchResult.
 * Skin::getSkinNameMessages() is deprecated and no longer used.
 * The mediawiki.RegExp module is deprecated; use mw.util.escapeRegExp() instead.
+* Specifying a SpecialPage object for the list of special pages (either through
+  the SpecialPage_initList hook or by adding to $wgSpecialPages) is now
+  deprecated.
+* Use of ActorMigration with 'ar_user', 'img_user', 'oi_user', 'fa_user',
+  'rc_user', 'log_user', and 'ipb_by' is deprecated. Queries should be adjusted
+  to use the corresponding actor fields directly. Note that use with
+  'rev_user' is *not* deprecated at this time.
+* Specifying both the class and factory parameters for
+  ApiModuleManager::addModule is now deprecated. The ObjectFactory spec should
+  be used instead.
+* The UserIsHidden hook is deprecated. Use GetUserBlock instead, and add a
+  system block that hides the user.
+* The GetBlockedStatus hook is deprecated. Use GetUserBlock instead, to add or
+  remove a block.
+* $wgContentHandlerUseDB is deprecated and should always be true.
 
 === Other changes in 1.34 ===
 * …
diff --git a/api.php b/api.php
index fe13263..6f4bac3 100644 (file)
--- a/api.php
+++ b/api.php
@@ -31,6 +31,7 @@ use MediaWiki\Logger\LegacyLogger;
 
 // So extensions (and other code) can check whether they're running in API mode
 define( 'MW_API', true );
+define( 'MW_ENTRY_POINT', 'api' );
 
 require __DIR__ . '/includes/WebStart.php';
 
index 0255a23..f95e001 100644 (file)
@@ -20,7 +20,6 @@ $wgAutoloadLocalClasses = [
        'AllMessagesTablePager' => __DIR__ . '/includes/specials/pagers/AllMessagesTablePager.php',
        'AllTrans' => __DIR__ . '/maintenance/language/alltrans.php',
        'AlphabeticPager' => __DIR__ . '/includes/pager/AlphabeticPager.php',
-       'AncientPagesPage' => __DIR__ . '/includes/specials/SpecialAncientpages.php',
        'AnsiTermColorer' => __DIR__ . '/maintenance/term/MWTerm.php',
        'ApiAMCreateAccount' => __DIR__ . '/includes/api/ApiAMCreateAccount.php',
        'ApiAuthManagerHelper' => __DIR__ . '/includes/api/ApiAuthManagerHelper.php',
@@ -215,7 +214,6 @@ $wgAutoloadLocalClasses = [
        'BlockLogFormatter' => __DIR__ . '/includes/logging/BlockLogFormatter.php',
        'BmpHandler' => __DIR__ . '/includes/media/BmpHandler.php',
        'BotPassword' => __DIR__ . '/includes/user/BotPassword.php',
-       'BrokenRedirectsPage' => __DIR__ . '/includes/specials/SpecialBrokenRedirects.php',
        'BufferingStatsdDataFactory' => __DIR__ . '/includes/libs/stats/BufferingStatsdDataFactory.php',
        'CLIParser' => __DIR__ . '/maintenance/parse.php',
        'CSSMin' => __DIR__ . '/includes/libs/CSSMin.php',
@@ -298,6 +296,7 @@ $wgAutoloadLocalClasses = [
        'ComposerJson' => __DIR__ . '/includes/libs/composer/ComposerJson.php',
        'ComposerLock' => __DIR__ . '/includes/libs/composer/ComposerLock.php',
        'ComposerPackageModifier' => __DIR__ . '/includes/composer/ComposerPackageModifier.php',
+       'ComposerPhpunitXmlCoverageEdit' => __DIR__ . '/includes/composer/ComposerPhpunitXmlCoverageEdit.php',
        'ComposerVendorHtaccessCreator' => __DIR__ . '/includes/composer/ComposerVendorHtaccessCreator.php',
        'ComposerVersionNormalizer' => __DIR__ . '/includes/composer/ComposerVersionNormalizer.php',
        'CompressOld' => __DIR__ . '/maintenance/storage/compressOld.php',
@@ -365,7 +364,6 @@ $wgAutoloadLocalClasses = [
        'DateFormats' => __DIR__ . '/maintenance/language/date-formats.php',
        'DateFormatter' => __DIR__ . '/includes/parser/DateFormatter.php',
        'DateFormatterFactory' => __DIR__ . '/includes/parser/DateFormatterFactory.php',
-       'DeadendPagesPage' => __DIR__ . '/includes/specials/SpecialDeadendpages.php',
        'DeduplicateArchiveRevId' => __DIR__ . '/maintenance/deduplicateArchiveRevId.php',
        'DeferrableCallback' => __DIR__ . '/includes/deferred/DeferrableCallback.php',
        'DeferrableUpdate' => __DIR__ . '/includes/deferred/DeferrableUpdate.php',
@@ -387,7 +385,6 @@ $wgAutoloadLocalClasses = [
        'DeletePageJob' => __DIR__ . '/includes/jobqueue/jobs/DeletePageJob.php',
        'DeleteSelfExternals' => __DIR__ . '/maintenance/deleteSelfExternals.php',
        'DeletedContribsPager' => __DIR__ . '/includes/specials/pagers/DeletedContribsPager.php',
-       'DeletedContributionsPage' => __DIR__ . '/includes/specials/SpecialDeletedContributions.php',
        'DependencyWrapper' => __DIR__ . '/includes/cache/dependency/DependencyWrapper.php',
        'DeprecatedGlobal' => __DIR__ . '/includes/DeprecatedGlobal.php',
        'DeprecatedInterfaceFinder' => __DIR__ . '/maintenance/findDeprecated.php',
@@ -413,7 +410,6 @@ $wgAutoloadLocalClasses = [
        'DjVuImage' => __DIR__ . '/includes/media/DjVuImage.php',
        'DnsSrvDiscoverer' => __DIR__ . '/includes/libs/DnsSrvDiscoverer.php',
        'DoubleRedirectJob' => __DIR__ . '/includes/jobqueue/jobs/DoubleRedirectJob.php',
-       'DoubleRedirectsPage' => __DIR__ . '/includes/specials/SpecialDoubleRedirects.php',
        'DummyLinker' => __DIR__ . '/includes/DummyLinker.php',
        'DummySearchIndexFieldDefinition' => __DIR__ . '/includes/search/DummySearchIndexFieldDefinition.php',
        'DummyTermColorer' => __DIR__ . '/maintenance/term/MWTerm.php',
@@ -446,8 +442,6 @@ $wgAutoloadLocalClasses = [
        'EditPage' => __DIR__ . '/includes/EditPage.php',
        'EditWatchlistCheckboxSeriesField' => __DIR__ . '/includes/specials/formfields/EditWatchlistCheckboxSeriesField.php',
        'EditWatchlistNormalHTMLForm' => __DIR__ . '/includes/specials/forms/EditWatchlistNormalHTMLForm.php',
-       'EmailConfirmation' => __DIR__ . '/includes/specials/SpecialConfirmemail.php',
-       'EmailInvalidation' => __DIR__ . '/includes/specials/SpecialEmailInvalidate.php',
        'EmailNotification' => __DIR__ . '/includes/mail/EmailNotification.php',
        'EmaillingJob' => __DIR__ . '/includes/jobqueue/jobs/EmaillingJob.php',
        'EmptyBagOStuff' => __DIR__ . '/includes/libs/objectcache/EmptyBagOStuff.php',
@@ -504,7 +498,6 @@ $wgAutoloadLocalClasses = [
        'FeedItem' => __DIR__ . '/includes/changes/FeedItem.php',
        'FeedUtils' => __DIR__ . '/includes/FeedUtils.php',
        'FetchText' => __DIR__ . '/maintenance/fetchText.php',
-       'FewestrevisionsPage' => __DIR__ . '/includes/specials/SpecialFewestrevisions.php',
        'Field' => __DIR__ . '/includes/libs/rdbms/field/Field.php',
        'File' => __DIR__ . '/includes/filerepo/file/File.php',
        'FileAwareNodeVisitor' => __DIR__ . '/maintenance/findDeprecated.php',
@@ -524,7 +517,6 @@ $wgAutoloadLocalClasses = [
        'FileContentsHasher' => __DIR__ . '/includes/utils/FileContentsHasher.php',
        'FileDeleteForm' => __DIR__ . '/includes/FileDeleteForm.php',
        'FileDependency' => __DIR__ . '/includes/cache/dependency/FileDependency.php',
-       'FileDuplicateSearchPage' => __DIR__ . '/includes/specials/SpecialFileDuplicateSearch.php',
        'FileJournal' => __DIR__ . '/includes/libs/filebackend/filejournal/FileJournal.php',
        'FileOp' => __DIR__ . '/includes/libs/filebackend/fileop/FileOp.php',
        'FileOpBatch' => __DIR__ . '/includes/libs/filebackend/FileOpBatch.php',
@@ -784,14 +776,11 @@ $wgAutoloadLocalClasses = [
        'LinkCache' => __DIR__ . '/includes/cache/LinkCache.php',
        'LinkFilter' => __DIR__ . '/includes/LinkFilter.php',
        'LinkHolderArray' => __DIR__ . '/includes/parser/LinkHolderArray.php',
-       'LinkSearchPage' => __DIR__ . '/includes/specials/SpecialLinkSearch.php',
        'Linker' => __DIR__ . '/includes/Linker.php',
        'LinksDeletionUpdate' => __DIR__ . '/includes/deferred/LinksDeletionUpdate.php',
        'LinksUpdate' => __DIR__ . '/includes/deferred/LinksUpdate.php',
-       'ListDuplicatedFilesPage' => __DIR__ . '/includes/specials/SpecialListDuplicatedFiles.php',
        'ListToggle' => __DIR__ . '/includes/ListToggle.php',
        'ListVariants' => __DIR__ . '/maintenance/language/listVariants.php',
-       'ListredirectsPage' => __DIR__ . '/includes/specials/SpecialListredirects.php',
        'LoadBalancer' => __DIR__ . '/includes/libs/rdbms/loadbalancer/LoadBalancer.php',
        'LoadBalancerSingle' => __DIR__ . '/includes/libs/rdbms/loadbalancer/LoadBalancerSingle.php',
        'LocalFile' => __DIR__ . '/includes/filerepo/file/LocalFile.php',
@@ -817,9 +806,6 @@ $wgAutoloadLocalClasses = [
        'LoggedUpdateMaintenance' => __DIR__ . '/maintenance/Maintenance.php',
        'LoginHelper' => __DIR__ . '/includes/specials/helpers/LoginHelper.php',
        'LoginSignupSpecialPage' => __DIR__ . '/includes/specialpage/LoginSignupSpecialPage.php',
-       'LonelyPagesPage' => __DIR__ . '/includes/specials/SpecialLonelypages.php',
-       'LongPagesPage' => __DIR__ . '/includes/specials/SpecialLongpages.php',
-       'MIMEsearchPage' => __DIR__ . '/includes/specials/SpecialMIMEsearch.php',
        'MSCompoundFileReader' => __DIR__ . '/includes/libs/mime/MSCompoundFileReader.php',
        'MWCallableUpdate' => __DIR__ . '/includes/deferred/MWCallableUpdate.php',
        'MWCallbackStream' => __DIR__ . '/includes/http/MWCallbackStream.php',
@@ -866,7 +852,6 @@ $wgAutoloadLocalClasses = [
        'McrUndoAction' => __DIR__ . '/includes/actions/McrUndoAction.php',
        'MediaHandler' => __DIR__ . '/includes/media/MediaHandler.php',
        'MediaHandlerFactory' => __DIR__ . '/includes/media/MediaHandlerFactory.php',
-       'MediaStatisticsPage' => __DIR__ . '/includes/specials/SpecialMediaStatistics.php',
        'MediaTransformError' => __DIR__ . '/includes/media/MediaTransformError.php',
        'MediaTransformInvalidParametersException' => __DIR__ . '/includes/media/MediaTransformInvalidParametersException.php',
        'MediaTransformOutput' => __DIR__ . '/includes/media/MediaTransformOutput.php',
@@ -1001,13 +986,7 @@ $wgAutoloadLocalClasses = [
        'MigrateUserGroup' => __DIR__ . '/maintenance/migrateUserGroup.php',
        'MimeAnalyzer' => __DIR__ . '/includes/libs/mime/MimeAnalyzer.php',
        'MinifyScript' => __DIR__ . '/maintenance/minify.php',
-       'MostcategoriesPage' => __DIR__ . '/includes/specials/SpecialMostcategories.php',
        'MostimagesPage' => __DIR__ . '/includes/specials/SpecialMostimages.php',
-       'MostinterwikisPage' => __DIR__ . '/includes/specials/SpecialMostinterwikis.php',
-       'MostlinkedCategoriesPage' => __DIR__ . '/includes/specials/SpecialMostlinkedcategories.php',
-       'MostlinkedPage' => __DIR__ . '/includes/specials/SpecialMostlinked.php',
-       'MostlinkedTemplatesPage' => __DIR__ . '/includes/specials/SpecialMostlinkedtemplates.php',
-       'MostrevisionsPage' => __DIR__ . '/includes/specials/SpecialMostrevisions.php',
        'MoveBatch' => __DIR__ . '/maintenance/moveBatch.php',
        'MoveFileOp' => __DIR__ . '/includes/libs/filebackend/fileop/MoveFileOp.php',
        'MoveLogFormatter' => __DIR__ . '/includes/logging/MoveLogFormatter.php',
@@ -1330,7 +1309,6 @@ $wgAutoloadLocalClasses = [
        'SerializedValueContainer' => __DIR__ . '/includes/libs/objectcache/serialized/SerializedValueContainer.php',
        'SevenZipStream' => __DIR__ . '/maintenance/includes/SevenZipStream.php',
        'ShiConverter' => __DIR__ . '/languages/classes/LanguageShi.php',
-       'ShortPagesPage' => __DIR__ . '/includes/specials/SpecialShortpages.php',
        'ShowJobs' => __DIR__ . '/maintenance/showJobs.php',
        'ShowSiteStats' => __DIR__ . '/maintenance/showSiteStats.php',
        'Site' => __DIR__ . '/includes/site/Site.php',
@@ -1357,6 +1335,7 @@ $wgAutoloadLocalClasses = [
        'SpecialAllMessages' => __DIR__ . '/includes/specials/SpecialAllMessages.php',
        'SpecialAllMyUploads' => __DIR__ . '/includes/specials/redirects/SpecialAllMyUploads.php',
        'SpecialAllPages' => __DIR__ . '/includes/specials/SpecialAllPages.php',
+       'SpecialAncientPages' => __DIR__ . '/includes/specials/SpecialAncientPages.php',
        'SpecialApiHelp' => __DIR__ . '/includes/specials/SpecialApiHelp.php',
        'SpecialApiSandbox' => __DIR__ . '/includes/specials/SpecialApiSandbox.php',
        'SpecialAutoblockList' => __DIR__ . '/includes/specials/SpecialAutoblockList.php',
@@ -1365,6 +1344,7 @@ $wgAutoloadLocalClasses = [
        'SpecialBlockList' => __DIR__ . '/includes/specials/SpecialBlockList.php',
        'SpecialBookSources' => __DIR__ . '/includes/specials/SpecialBookSources.php',
        'SpecialBotPasswords' => __DIR__ . '/includes/specials/SpecialBotPasswords.php',
+       'SpecialBrokenRedirects' => __DIR__ . '/includes/specials/SpecialBrokenRedirects.php',
        'SpecialCachedPage' => __DIR__ . '/includes/specials/SpecialCachedPage.php',
        'SpecialCategories' => __DIR__ . '/includes/specials/SpecialCategories.php',
        'SpecialChangeContentModel' => __DIR__ . '/includes/specials/SpecialChangeContentModel.php',
@@ -1372,35 +1352,55 @@ $wgAutoloadLocalClasses = [
        'SpecialChangeEmail' => __DIR__ . '/includes/specials/SpecialChangeEmail.php',
        'SpecialChangePassword' => __DIR__ . '/includes/specials/SpecialChangePassword.php',
        'SpecialComparePages' => __DIR__ . '/includes/specials/SpecialComparePages.php',
+       'SpecialConfirmEmail' => __DIR__ . '/includes/specials/SpecialConfirmEmail.php',
        'SpecialContributions' => __DIR__ . '/includes/specials/SpecialContributions.php',
        'SpecialCreateAccount' => __DIR__ . '/includes/specials/SpecialCreateAccount.php',
+       'SpecialDeadendPages' => __DIR__ . '/includes/specials/SpecialDeadendPages.php',
+       'SpecialDeletedContributions' => __DIR__ . '/includes/specials/SpecialDeletedContributions.php',
        'SpecialDiff' => __DIR__ . '/includes/specials/SpecialDiff.php',
+       'SpecialDoubleRedirects' => __DIR__ . '/includes/specials/SpecialDoubleRedirects.php',
        'SpecialEditTags' => __DIR__ . '/includes/specials/SpecialEditTags.php',
        'SpecialEditWatchlist' => __DIR__ . '/includes/specials/SpecialEditWatchlist.php',
+       'SpecialEmailInvalidate' => __DIR__ . '/includes/specials/SpecialEmailInvalidate.php',
        'SpecialEmailUser' => __DIR__ . '/includes/specials/SpecialEmailUser.php',
        'SpecialExpandTemplates' => __DIR__ . '/includes/specials/SpecialExpandTemplates.php',
        'SpecialExport' => __DIR__ . '/includes/specials/SpecialExport.php',
+       'SpecialFewestRevisions' => __DIR__ . '/includes/specials/SpecialFewestRevisions.php',
+       'SpecialFileDuplicateSearch' => __DIR__ . '/includes/specials/SpecialFileDuplicateSearch.php',
        'SpecialFilepath' => __DIR__ . '/includes/specials/SpecialFilepath.php',
        'SpecialGoToInterwiki' => __DIR__ . '/includes/specials/SpecialGoToInterwiki.php',
        'SpecialImport' => __DIR__ . '/includes/specials/SpecialImport.php',
        'SpecialJavaScriptTest' => __DIR__ . '/includes/specials/SpecialJavaScriptTest.php',
        'SpecialLinkAccounts' => __DIR__ . '/includes/specials/SpecialLinkAccounts.php',
+       'SpecialLinkSearch' => __DIR__ . '/includes/specials/SpecialLinkSearch.php',
        'SpecialListAdmins' => __DIR__ . '/includes/specials/redirects/SpecialListAdmins.php',
        'SpecialListBots' => __DIR__ . '/includes/specials/redirects/SpecialListBots.php',
+       'SpecialListDuplicatedFiles' => __DIR__ . '/includes/specials/SpecialListDuplicatedFiles.php',
        'SpecialListFiles' => __DIR__ . '/includes/specials/SpecialListFiles.php',
        'SpecialListGrants' => __DIR__ . '/includes/specials/SpecialListGrants.php',
        'SpecialListGroupRights' => __DIR__ . '/includes/specials/SpecialListGroupRights.php',
+       'SpecialListRedirects' => __DIR__ . '/includes/specials/SpecialListRedirects.php',
        'SpecialListUsers' => __DIR__ . '/includes/specials/SpecialListUsers.php',
        'SpecialLockdb' => __DIR__ . '/includes/specials/SpecialLockdb.php',
        'SpecialLog' => __DIR__ . '/includes/specials/SpecialLog.php',
+       'SpecialLonelyPages' => __DIR__ . '/includes/specials/SpecialLonelyPages.php',
+       'SpecialLongPages' => __DIR__ . '/includes/specials/SpecialLongPages.php',
+       'SpecialMIMESearch' => __DIR__ . '/includes/specials/SpecialMIMESearch.php',
+       'SpecialMediaStatistics' => __DIR__ . '/includes/specials/SpecialMediaStatistics.php',
        'SpecialMergeHistory' => __DIR__ . '/includes/specials/SpecialMergeHistory.php',
+       'SpecialMostCategories' => __DIR__ . '/includes/specials/SpecialMostCategories.php',
+       'SpecialMostInterwikis' => __DIR__ . '/includes/specials/SpecialMostInterwikis.php',
+       'SpecialMostLinked' => __DIR__ . '/includes/specials/SpecialMostLinked.php',
+       'SpecialMostLinkedCategories' => __DIR__ . '/includes/specials/SpecialMostLinkedCategories.php',
+       'SpecialMostLinkedTemplates' => __DIR__ . '/includes/specials/SpecialMostLinkedTemplates.php',
+       'SpecialMostRevisions' => __DIR__ . '/includes/specials/SpecialMostRevisions.php',
        'SpecialMute' => __DIR__ . '/includes/specials/SpecialMute.php',
        'SpecialMyLanguage' => __DIR__ . '/includes/specials/SpecialMyLanguage.php',
        'SpecialMycontributions' => __DIR__ . '/includes/specials/redirects/SpecialMycontributions.php',
        'SpecialMypage' => __DIR__ . '/includes/specials/redirects/SpecialMypage.php',
        'SpecialMytalk' => __DIR__ . '/includes/specials/redirects/SpecialMytalk.php',
        'SpecialMyuploads' => __DIR__ . '/includes/specials/redirects/SpecialMyuploads.php',
-       'SpecialNewFiles' => __DIR__ . '/includes/specials/SpecialNewimages.php',
+       'SpecialNewFiles' => __DIR__ . '/includes/specials/SpecialNewFiles.php',
        'SpecialNewSection' => __DIR__ . '/includes/specials/SpecialNewSection.php',
        'SpecialNewpages' => __DIR__ . '/includes/specials/SpecialNewpages.php',
        'SpecialPage' => __DIR__ . '/includes/specialpage/SpecialPage.php',
@@ -1428,22 +1428,34 @@ $wgAutoloadLocalClasses = [
        'SpecialRevisionDelete' => __DIR__ . '/includes/specials/SpecialRevisionDelete.php',
        'SpecialRunJobs' => __DIR__ . '/includes/specials/SpecialRunJobs.php',
        'SpecialSearch' => __DIR__ . '/includes/specials/SpecialSearch.php',
+       'SpecialShortPages' => __DIR__ . '/includes/specials/SpecialShortPages.php',
        'SpecialSpecialpages' => __DIR__ . '/includes/specials/SpecialSpecialpages.php',
        'SpecialStatistics' => __DIR__ . '/includes/specials/SpecialStatistics.php',
        'SpecialTags' => __DIR__ . '/includes/specials/SpecialTags.php',
        'SpecialTrackingCategories' => __DIR__ . '/includes/specials/SpecialTrackingCategories.php',
        'SpecialUnblock' => __DIR__ . '/includes/specials/SpecialUnblock.php',
+       'SpecialUncategorizedCategories' => __DIR__ . '/includes/specials/SpecialUncategorizedCategories.php',
+       'SpecialUncategorizedImages' => __DIR__ . '/includes/specials/SpecialUncategorizedImages.php',
+       'SpecialUncategorizedPages' => __DIR__ . '/includes/specials/SpecialUncategorizedPages.php',
+       'SpecialUncategorizedTemplates' => __DIR__ . '/includes/specials/SpecialUncategorizedTemplates.php',
        'SpecialUndelete' => __DIR__ . '/includes/specials/SpecialUndelete.php',
        'SpecialUnlinkAccounts' => __DIR__ . '/includes/specials/SpecialUnlinkAccounts.php',
        'SpecialUnlockdb' => __DIR__ . '/includes/specials/SpecialUnlockdb.php',
+       'SpecialUnusedCategories' => __DIR__ . '/includes/specials/SpecialUnusedCategories.php',
+       'SpecialUnusedImages' => __DIR__ . '/includes/specials/SpecialUnusedImages.php',
+       'SpecialUnusedTemplates' => __DIR__ . '/includes/specials/SpecialUnusedTemplates.php',
+       'SpecialUnwatchedPages' => __DIR__ . '/includes/specials/SpecialUnwatchedPages.php',
        'SpecialUpload' => __DIR__ . '/includes/specials/SpecialUpload.php',
        'SpecialUploadStash' => __DIR__ . '/includes/specials/SpecialUploadStash.php',
        'SpecialUploadStashTooLargeException' => __DIR__ . '/includes/specials/exception/SpecialUploadStashTooLargeException.php',
        'SpecialUserLogin' => __DIR__ . '/includes/specials/SpecialUserLogin.php',
        'SpecialUserLogout' => __DIR__ . '/includes/specials/SpecialUserLogout.php',
        'SpecialVersion' => __DIR__ . '/includes/specials/SpecialVersion.php',
+       'SpecialWantedCategories' => __DIR__ . '/includes/specials/SpecialWantedCategories.php',
+       'SpecialWantedTemplates' => __DIR__ . '/includes/specials/SpecialWantedTemplates.php',
        'SpecialWatchlist' => __DIR__ . '/includes/specials/SpecialWatchlist.php',
        'SpecialWhatLinksHere' => __DIR__ . '/includes/specials/SpecialWhatLinksHere.php',
+       'SpecialWithoutInterwiki' => __DIR__ . '/includes/specials/SpecialWithoutInterwiki.php',
        'SqlBagOStuff' => __DIR__ . '/includes/objectcache/SqlBagOStuff.php',
        'SqlSearchResult' => __DIR__ . '/includes/search/SqlSearchResult.php',
        'SqlSearchResultSet' => __DIR__ . '/includes/search/SqlSearchResultSet.php',
@@ -1516,10 +1528,6 @@ $wgAutoloadLocalClasses = [
        'UDPTransport' => __DIR__ . '/includes/libs/UDPTransport.php',
        'UIDGenerator' => __DIR__ . '/includes/utils/UIDGenerator.php',
        'UcdXmlReader' => __DIR__ . '/maintenance/language/generateCollationData.php',
-       'UncategorizedCategoriesPage' => __DIR__ . '/includes/specials/SpecialUncategorizedcategories.php',
-       'UncategorizedImagesPage' => __DIR__ . '/includes/specials/SpecialUncategorizedimages.php',
-       'UncategorizedPagesPage' => __DIR__ . '/includes/specials/SpecialUncategorizedpages.php',
-       'UncategorizedTemplatesPage' => __DIR__ . '/includes/specials/SpecialUncategorizedtemplates.php',
        'Undelete' => __DIR__ . '/maintenance/undelete.php',
        'UnifiedDiffFormatter' => __DIR__ . '/includes/diff/UnifiedDiffFormatter.php',
        'UnknownContent' => __DIR__ . '/includes/content/UnknownContent.php',
@@ -1528,11 +1536,7 @@ $wgAutoloadLocalClasses = [
        'UnprotectAction' => __DIR__ . '/includes/actions/UnprotectAction.php',
        'UnregisteredLocalFile' => __DIR__ . '/includes/filerepo/file/UnregisteredLocalFile.php',
        'UnsupportedSlotDiffRenderer' => __DIR__ . '/includes/diff/UnsupportedSlotDiffRenderer.php',
-       'UnusedCategoriesPage' => __DIR__ . '/includes/specials/SpecialUnusedcategories.php',
-       'UnusedimagesPage' => __DIR__ . '/includes/specials/SpecialUnusedimages.php',
-       'UnusedtemplatesPage' => __DIR__ . '/includes/specials/SpecialUnusedtemplates.php',
        'UnwatchAction' => __DIR__ . '/includes/actions/UnwatchAction.php',
-       'UnwatchedpagesPage' => __DIR__ . '/includes/specials/SpecialUnwatchedpages.php',
        'UpdateArticleCount' => __DIR__ . '/maintenance/updateArticleCount.php',
        'UpdateCollation' => __DIR__ . '/maintenance/updateCollation.php',
        'UpdateDoubleWidthSearch' => __DIR__ . '/maintenance/updateDoubleWidthSearch.php',
@@ -1596,11 +1600,9 @@ $wgAutoloadLocalClasses = [
        'WANCacheReapUpdate' => __DIR__ . '/includes/deferred/WANCacheReapUpdate.php',
        'WANObjectCache' => __DIR__ . '/includes/libs/objectcache/wancache/WANObjectCache.php',
        'WANObjectCacheReaper' => __DIR__ . '/includes/libs/objectcache/wancache/WANObjectCacheReaper.php',
-       'WantedCategoriesPage' => __DIR__ . '/includes/specials/SpecialWantedcategories.php',
        'WantedFilesPage' => __DIR__ . '/includes/specials/SpecialWantedfiles.php',
        'WantedPagesPage' => __DIR__ . '/includes/specials/SpecialWantedpages.php',
        'WantedQueryPage' => __DIR__ . '/includes/specialpage/WantedQueryPage.php',
-       'WantedTemplatesPage' => __DIR__ . '/includes/specials/SpecialWantedtemplates.php',
        'WatchAction' => __DIR__ . '/includes/actions/WatchAction.php',
        'WatchedItem' => __DIR__ . '/includes/watcheditem/WatchedItem.php',
        'WatchedItemQueryService' => __DIR__ . '/includes/watcheditem/WatchedItemQueryService.php',
@@ -1704,7 +1706,6 @@ $wgAutoloadLocalClasses = [
        'WikitextContentHandler' => __DIR__ . '/includes/content/WikitextContentHandler.php',
        'WikitextLogFormatter' => __DIR__ . '/includes/logging/WikitextLogFormatter.php',
        'WinCacheBagOStuff' => __DIR__ . '/includes/libs/objectcache/WinCacheBagOStuff.php',
-       'WithoutInterwikiPage' => __DIR__ . '/includes/specials/SpecialWithoutinterwiki.php',
        'WordLevelDiff' => __DIR__ . '/includes/diff/WordLevelDiff.php',
        'WrapOldPasswords' => __DIR__ . '/maintenance/wrapOldPasswords.php',
        'XCFHandler' => __DIR__ . '/includes/media/XCFHandler.php',
index ac89d71..5785873 100644 (file)
@@ -28,7 +28,7 @@
                "ext-xml": "*",
                "guzzlehttp/guzzle": "6.3.3",
                "liuggio/statsd-php-client": "1.0.18",
-               "oojs/oojs-ui": "0.34.0",
+               "oojs/oojs-ui": "0.34.1",
                "pear/mail": "1.4.1",
                "pear/mail_mime": "1.10.2",
                "pear/net_smtp": "1.8.1",
@@ -97,7 +97,8 @@
        "autoload": {
                "psr-0": {
                        "ComposerHookHandler": "includes/composer",
-                       "ComposerVendorHtaccessCreator": "includes/composer"
+                       "ComposerVendorHtaccessCreator": "includes/composer",
+                       "ComposerPhpunitXmlCoverageEdit":"includes/composer"
                }
        },
        "autoload-dev": {
                "phpunit": "phpunit",
                "phpunit:unit": "phpunit --colors=always --testsuite=core:unit,extensions:unit,skins:unit",
                "phpunit:integration": "phpunit --colors=always --testsuite=core:integration,extensions:integration,skins:integration",
-               "phpunit:coverage": "phpunit --testsuite=core:unit --exclude-group Dump,Broken"
+               "phpunit:coverage": "phpunit --testsuite=core:unit --exclude-group Dump,Broken",
+               "phpunit:coverage-edit": "ComposerPhpunitXmlCoverageEdit::onEvent"
        },
        "config": {
                "optimize-autoloader": true,
index 9ce016f..06701cd 100644 (file)
                },
                "SpecialPages": {
                        "type": "object",
-                       "description": "SpecialPages implemented in this extension (mapping of page name to class name)"
+                       "description": "SpecialPages implemented in this extension (mapping of page name to class name or to ObjectFactory spec)"
                },
                "AutoloadNamespaces": {
                        "type": "object",
index 9d874f4..56d274b 100644 (file)
                },
                "SpecialPages": {
                        "type": "object",
-                       "description": "SpecialPages implemented in this extension (mapping of page name to class name)"
+                       "description": "SpecialPages implemented in this extension (mapping of page name to class name or to ObjectFactory spec)"
                },
                "AutoloadNamespaces": {
                        "type": "object",
index a248c29..43bfd8d 100644 (file)
@@ -1585,7 +1585,8 @@ entitled to be in.
 $user: user to promote.
 &$promote: groups that will be added.
 
-'GetBlockedStatus': after loading blocking status of an user from the database
+'GetBlockedStatus': DEPRECATED since 1.34 - use GetUserBlock instead. After
+loading blocking status of a user from the database
 &$user: user (object) being checked
 
 'GetCacheVaryCookies': Get cookies that should vary cache options.
@@ -3729,7 +3730,9 @@ $ip: User's IP address
 false if a UserGetRights hook might remove the named right.
 $right: The user right being checked
 
-'UserIsHidden': Check if the user's name should be hidden. See User::isHidden().
+'UserIsHidden': DEPRECATED since 1.34 - use GetUserBlock instead, and add a
+system block that hides the user. Check if the user's name should be hidden.
+See User::isHidden().
 $user: User in question.
 &$hidden: Set true if the user's name should be hidden.
 
index 6e45e4e..f23de4f 100644 (file)
@@ -39,6 +39,7 @@
  */
 
 define( 'MW_NO_OUTPUT_COMPRESSION', 1 );
+define( 'MW_ENTRY_POINT', 'img_auth' );
 require __DIR__ . '/includes/WebStart.php';
 
 # Set action base paths so that WebRequest::getPathInfo()
index 5dde8a0..c79074d 100644 (file)
@@ -28,15 +28,18 @@ use Wikimedia\Rdbms\IDatabase;
  * This class handles the logic for the actor table migration.
  *
  * This is not intended to be a long-term part of MediaWiki; it will be
- * deprecated and removed along with $wgActorTableSchemaMigrationStage.
+ * deprecated and removed once actor migration is complete.
  *
  * @since 1.31
+ * @since 1.34 Use with 'ar_user', 'img_user', 'oi_user', 'fa_user',
+ *  'rc_user', 'log_user', and 'ipb_by' is deprecated. Callers should
+ *  reference the corresponding actor fields directly.
  */
 class ActorMigration {
 
        /**
         * Constant for extensions to feature-test whether $wgActorTableSchemaMigrationStage
-        * expects MIGRATION_* or SCHEMA_COMPAT_*
+        * (in MW <1.34) expects MIGRATION_* or SCHEMA_COMPAT_*
         */
        const MIGRATION_STAGE_SCHEMA_COMPAT = 1;
 
@@ -68,6 +71,28 @@ class ActorMigration {
         */
        private static $formerTempTables = [];
 
+       /**
+        * Define fields that are deprecated for use with this class.
+        * @var (string|null)[] Keys are '$key', value is null for soft deprecation
+        *  or a string naming the deprecated version for hard deprecation.
+        */
+       private static $deprecated = [
+               'ar_user' => null, // 1.34
+               'img_user' => null, // 1.34
+               'oi_user' => null, // 1.34
+               'fa_user' => null, // 1.34
+               'rc_user' => null, // 1.34
+               'log_user' => null, // 1.34
+               'ipb_by' => null, // 1.34
+       ];
+
+       /**
+        * Define fields that are removed for use with this class.
+        * @var string[] Keys are '$key', value is the MediaWiki version in which
+        *  use was removed.
+        */
+       private static $removed = [];
+
        /**
         * Define fields that use non-standard mapping
         * @var array Keys are the user id column name, values are arrays with two
@@ -112,6 +137,21 @@ class ActorMigration {
                return MediaWikiServices::getInstance()->getActorMigration();
        }
 
+       /**
+        * Issue deprecation warning/error as appropriate.
+        * @param string $key
+        */
+       private static function checkDeprecation( $key ) {
+               if ( isset( self::$removed[$key] ) ) {
+                       throw new InvalidArgumentException(
+                               "Use of " . static::class . " for '$key' was removed in MediaWiki " . self::$removed[$key]
+                       );
+               }
+               if ( !empty( self::$deprecated[$key] ) ) {
+                       wfDeprecated( static::class . " for '$key'", self::$deprecated[$key], false, 3 );
+               }
+       }
+
        /**
         * Return an SQL condition to test if a user field is anonymous
         * @param string $field Field name or SQL fragment
@@ -152,6 +192,8 @@ class ActorMigration {
         * @phan-return array{tables:string[],fields:string[],joins:array}
         */
        public function getJoin( $key ) {
+               self::checkDeprecation( $key );
+
                if ( !isset( $this->joinCache[$key] ) ) {
                        $tables = [];
                        $fields = [];
@@ -203,6 +245,8 @@ class ActorMigration {
         * @return array to merge into `$values` to `IDatabase->update()` or `$a` to `IDatabase->insert()`
         */
        public function getInsertValues( IDatabase $dbw, $key, UserIdentity $user ) {
+               self::checkDeprecation( $key );
+
                if ( isset( self::$tempTables[$key] ) ) {
                        throw new InvalidArgumentException( "Must use getInsertValuesWithTempTable() for $key" );
                }
@@ -236,6 +280,8 @@ class ActorMigration {
         *    and extra fields needed for the temp table.
         */
        public function getInsertValuesWithTempTable( IDatabase $dbw, $key, UserIdentity $user ) {
+               self::checkDeprecation( $key );
+
                if ( isset( self::$formerTempTables[$key] ) ) {
                        wfDeprecated( __METHOD__ . " for $key", self::$formerTempTables[$key] );
                } elseif ( !isset( self::$tempTables[$key] ) ) {
@@ -319,6 +365,8 @@ class ActorMigration {
         *  All tables and joins are aliased, so `+` is safe to use.
         */
        public function getWhere( IDatabase $db, $key, $users, $useId = true ) {
+               self::checkDeprecation( $key );
+
                $tables = [];
                $conds = [];
                $joins = [];
index 323c5d3..0664652 100644 (file)
@@ -182,16 +182,7 @@ class AjaxResponse {
                        if ( $this->mConfig->get( 'UseCdn' ) ) {
                                # Expect explicit purge of the proxy cache, but require end user agents
                                # to revalidate against the proxy on each visit.
-                               # Surrogate-Control controls our CDN, Cache-Control downstream caches
-
-                               if ( $this->mConfig->get( 'UseESI' ) ) {
-                                       wfDeprecated( '$wgUseESI = true', '1.33' );
-                                       header( 'Surrogate-Control: max-age=' . $this->mCacheDuration . ', content="ESI/1.0"' );
-                                       header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
-                               } else {
-                                       header( 'Cache-Control: s-maxage=' . $this->mCacheDuration . ', must-revalidate, max-age=0' );
-                               }
-
+                               header( 'Cache-Control: s-maxage=' . $this->mCacheDuration . ', must-revalidate, max-age=0' );
                        } else {
                                # Let the client do the caching. Cache is not purged.
                                header( "Expires: " . gmdate( "D, d M Y H:i:s", time() + $this->mCacheDuration ) . " GMT" );
index 5d3fba7..47fd073 100644 (file)
@@ -2748,12 +2748,6 @@ $wgExtensionInfoMTime = false;
  */
 $wgUseCdn = false;
 
-/**
- * If you run Squid3 with ESI support, enable this (default:false):
- * @deprecated in 1.33. This was a now-defunct experimental feature.
- */
-$wgUseESI = false;
-
 /**
  * Add X-Forwarded-Proto to the Vary and Key headers for API requests and
  * RSS/Atom feeds. Use this if you have an SSL termination setup
@@ -4894,6 +4888,7 @@ $wgDefaultUserOptions = [
        'wllimit' => 250,
        'useeditwarning' => 1,
        'prefershttps' => 1,
+       'requireemail' => 0,
 ];
 
 /**
@@ -4963,6 +4958,15 @@ $wgSessionProviders = [
        ],
 ];
 
+/**
+ * Temporary feature flag that controls whether users will see a checkbox allowing them to
+ * require providing email during password resets.
+ *
+ * @deprecated This feature is under development, don't assume this flag's existence or function
+ *     outside of MediaWiki.
+ */
+$wgAllowRequiringEmailForResets = false;
+
 /** @} */ # end user accounts }
 
 /************************************************************************//**
@@ -8615,6 +8619,7 @@ $wgContentHandlerTextFallback = 'ignore';
  * handling is less robust and less flexible.
  *
  * @since 1.21
+ * @deprecated since 1.34, and should always be set true.
  */
 $wgContentHandlerUseDB = true;
 
@@ -8985,24 +8990,6 @@ $wgMultiContentRevisionSchemaMigrationStage = SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_
  */
 $wgXmlDumpSchemaVersion = XML_DUMP_SCHEMA_VERSION_10;
 
-/**
- * Actor table schema migration stage.
- *
- * Use the SCHEMA_COMPAT_XXX flags. Supported values:
- * - SCHEMA_COMPAT_OLD
- * - SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
- * - SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW
- * - SCHEMA_COMPAT_NEW
- *
- * Note that reading the old and new schema at the same time is not supported
- * in 1.32, but was (with significant query performance issues) in 1.31.
- *
- * @since 1.31
- * @since 1.32 changed allowed flags
- * @var int An appropriate combination of SCHEMA_COMPAT_XXX flags.
- */
-$wgActorTableSchemaMigrationStage = SCHEMA_COMPAT_NEW;
-
 /**
  * Flag to enable Partial Blocks. This allows an admin to prevent a user from editing specific pages
  * or namespaces.
index 564c8f4..634e7af 100644 (file)
@@ -473,6 +473,7 @@ class MovePage {
 
                        $mp = new MovePage( $oldSubpage, $newSubpage );
                        $method = $checkPermissions ? 'moveIfAllowed' : 'move';
+                       /** @var Status $status */
                        $status = $mp->$method( $user, $reason, $createRedirect, $changeTags );
                        if ( $status->isOK() ) {
                                $status->setResult( true, $newSubpage->getPrefixedText() );
@@ -508,7 +509,7 @@ class MovePage {
 
                Hooks::run( 'TitleMoveStarting', [ $this->oldTitle, $this->newTitle, $user ] );
 
-               $pageid = $this->oldTitle->getArticleID( Title::GAID_FOR_UPDATE );
+               $pageid = $this->oldTitle->getArticleID( Title::READ_LATEST );
                $protected = $this->oldTitle->isProtected();
 
                // Do the actual move; if this fails, it will throw an MWException(!)
index 15a759b..9dbbf13 100644 (file)
@@ -2414,32 +2414,16 @@ class OutputPage extends ContextSource {
                                $this->mCdnMaxage != 0 &&
                                !$this->haveCacheVaryCookies()
                        ) {
-                               if ( $config->get( 'UseESI' ) ) {
-                                       wfDeprecated( '$wgUseESI = true', '1.33' );
-                                       # We'll purge the proxy cache explicitly, but require end user agents
-                                       # to revalidate against the proxy on each visit.
-                                       # Surrogate-Control controls our CDN, Cache-Control downstream caches
-                                       wfDebug( __METHOD__ .
-                                               ": proxy caching with ESI; {$this->mLastModified} **", 'private' );
-                                       # start with a shorter timeout for initial testing
-                                       # header( 'Surrogate-Control: max-age=2678400+2678400, content="ESI/1.0"');
-                                       $response->header(
-                                               "Surrogate-Control: max-age={$config->get( 'CdnMaxAge' )}" .
-                                               "+{$this->mCdnMaxage}, content=\"ESI/1.0\""
-                                       );
-                                       $response->header( 'Cache-Control: s-maxage=0, must-revalidate, max-age=0' );
-                               } else {
-                                       # We'll purge the proxy cache for anons explicitly, but require end user agents
-                                       # to revalidate against the proxy on each visit.
-                                       # IMPORTANT! The CDN needs to replace the Cache-Control header with
-                                       # Cache-Control: s-maxage=0, must-revalidate, max-age=0
-                                       wfDebug( __METHOD__ .
-                                               ": local proxy caching; {$this->mLastModified} **", 'private' );
-                                       # start with a shorter timeout for initial testing
-                                       # header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
-                                       $response->header( "Cache-Control: " .
-                                               "s-maxage={$this->mCdnMaxage}, must-revalidate, max-age=0" );
-                               }
+                               # We'll purge the proxy cache for anons explicitly, but require end user agents
+                               # to revalidate against the proxy on each visit.
+                               # IMPORTANT! The CDN needs to replace the Cache-Control header with
+                               # Cache-Control: s-maxage=0, must-revalidate, max-age=0
+                               wfDebug( __METHOD__ .
+                                       ": local proxy caching; {$this->mLastModified} **", 'private' );
+                               # start with a shorter timeout for initial testing
+                               # header( "Cache-Control: s-maxage=2678400, must-revalidate, max-age=0" );
+                               $response->header( "Cache-Control: " .
+                                       "s-maxage={$this->mCdnMaxage}, must-revalidate, max-age=0" );
                        } else {
                                # We do want clients to cache if they can, but they *must* check for updates
                                # on revisiting the page.
@@ -2838,7 +2822,7 @@ class OutputPage extends ContextSource {
        /**
         * Add a "return to" link pointing to a specified title
         *
-        * @param Title $title Title to link
+        * @param LinkTarget $title Title to link
         * @param array $query Query string parameters
         * @param string|null $text Text of the link (input is not escaped)
         * @param array $options Options array to pass to Linker
index b63a84d..bf138c4 100644 (file)
@@ -31,8 +31,6 @@
  *
  * @note This class uses setter methods instead of a constructor so that
  * it can be compatible with PHP 4, PHP 5 and PHP 7 (without warnings).
- *
- * @class
  */
 class PHPVersionCheck {
        /* @var string The number of the MediaWiki version used. */
index 8b5d995..a1be271 100644 (file)
@@ -58,6 +58,18 @@ class ProtectionForm {
        /** @var array Map of action to the expiry time of the existing protection */
        protected $mExistingExpiry = [];
 
+       /** @var Article */
+       protected $mArticle;
+
+       /** @var Title */
+       protected $mTitle;
+
+       /** @var bool */
+       protected $disabled;
+
+       /** @var array */
+       protected $disabledAttrib;
+
        /** @var IContextSource */
        private $mContext;
 
@@ -78,7 +90,7 @@ class ProtectionForm {
                if ( wfReadOnly() ) {
                        $this->mPermErrors[] = [ 'readonlytext', wfReadOnlyReason() ];
                }
-               $this->disabled = $this->mPermErrors != [];
+               $this->disabled = $this->mPermErrors !== [];
                $this->disabledAttrib = $this->disabled
                        ? [ 'disabled' => 'disabled' ]
                        : [];
index c6e727e..828f647 100644 (file)
@@ -298,203 +298,6 @@ class Revision implements IDBAccessObject {
                return $rec ? new Revision( $rec ) : null;
        }
 
-       /**
-        * Return the value of a select() JOIN conds array for the user table.
-        * This will get user table rows for logged-in users.
-        * @since 1.19
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'user' ] ) instead.
-        * @return array
-        */
-       public static function userJoinCond() {
-               global $wgActorTableSchemaMigrationStage;
-
-               wfDeprecated( __METHOD__, '1.31' );
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's
-                       // no way the join it's trying to do can work once the old fields
-                       // aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               return [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ];
-       }
-
-       /**
-        * Return the value of a select() page conds array for the page table.
-        * This will assure that the revision(s) are not orphaned from live pages.
-        * @since 1.19
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'page' ] ) instead.
-        * @return array
-        */
-       public static function pageJoinCond() {
-               wfDeprecated( __METHOD__, '1.31' );
-               return [ 'JOIN', [ 'page_id = rev_page' ] ];
-       }
-
-       /**
-        * Return the list of revision fields that should be selected to create
-        * a new revision.
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo() instead.
-        * @return array
-        */
-       public static function selectFields() {
-               global $wgContentHandlerUseDB, $wgActorTableSchemaMigrationStage;
-               global $wgMultiContentRevisionSchemaMigrationStage;
-
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->rev_user or $row->rev_user_text and we can't give it
-                       // useful values here once those aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               if ( !( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->rev_text_id or $row->rev_content_model and we can't give it
-                       // useful values here once those aren't being written anymore,
-                       // and may not exist at all.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__ . ' when $wgMultiContentRevisionSchemaMigrationStage '
-                               . 'does not have SCHEMA_COMPAT_WRITE_OLD set.'
-                       );
-               }
-
-               wfDeprecated( __METHOD__, '1.31' );
-
-               $fields = [
-                       'rev_id',
-                       'rev_page',
-                       'rev_text_id',
-                       'rev_timestamp',
-                       'rev_user_text',
-                       'rev_user',
-                       'rev_actor' => 'NULL',
-                       'rev_minor_edit',
-                       'rev_deleted',
-                       'rev_len',
-                       'rev_parent_id',
-                       'rev_sha1',
-               ];
-
-               $fields += CommentStore::getStore()->getFields( 'rev_comment' );
-
-               if ( $wgContentHandlerUseDB ) {
-                       $fields[] = 'rev_content_format';
-                       $fields[] = 'rev_content_model';
-               }
-
-               return $fields;
-       }
-
-       /**
-        * Return the list of revision fields that should be selected to create
-        * a new revision from an archive row.
-        * @deprecated since 1.31, use RevisionStore::getArchiveQueryInfo() instead.
-        * @return array
-        */
-       public static function selectArchiveFields() {
-               global $wgContentHandlerUseDB, $wgActorTableSchemaMigrationStage;
-               global $wgMultiContentRevisionSchemaMigrationStage;
-
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->ar_user or $row->ar_user_text and we can't give it
-                       // useful values here once those aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               if ( !( $wgMultiContentRevisionSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->ar_text_id or $row->ar_content_model and we can't give it
-                       // useful values here once those aren't being written anymore,
-                       // and may not exist at all.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__ . ' when $wgMultiContentRevisionSchemaMigrationStage '
-                               . 'does not have SCHEMA_COMPAT_WRITE_OLD set.'
-                       );
-               }
-
-               wfDeprecated( __METHOD__, '1.31' );
-
-               $fields = [
-                       'ar_id',
-                       'ar_page_id',
-                       'ar_rev_id',
-                       'ar_text_id',
-                       'ar_timestamp',
-                       'ar_user_text',
-                       'ar_user',
-                       'ar_actor' => 'NULL',
-                       'ar_minor_edit',
-                       'ar_deleted',
-                       'ar_len',
-                       'ar_parent_id',
-                       'ar_sha1',
-               ];
-
-               $fields += CommentStore::getStore()->getFields( 'ar_comment' );
-
-               if ( $wgContentHandlerUseDB ) {
-                       $fields[] = 'ar_content_format';
-                       $fields[] = 'ar_content_model';
-               }
-               return $fields;
-       }
-
-       /**
-        * Return the list of text fields that should be selected to read the
-        * revision text
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'text' ] ) instead.
-        * @return array
-        */
-       public static function selectTextFields() {
-               wfDeprecated( __METHOD__, '1.31' );
-               return [
-                       'old_text',
-                       'old_flags'
-               ];
-       }
-
-       /**
-        * Return the list of page fields that should be selected from page table
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'page' ] ) instead.
-        * @return array
-        */
-       public static function selectPageFields() {
-               wfDeprecated( __METHOD__, '1.31' );
-               return [
-                       'page_namespace',
-                       'page_title',
-                       'page_id',
-                       'page_latest',
-                       'page_is_redirect',
-                       'page_len',
-               ];
-       }
-
-       /**
-        * Return the list of user fields that should be selected from user table
-        * @deprecated since 1.31, use RevisionStore::getQueryInfo( [ 'user' ] ) instead.
-        * @return array
-        */
-       public static function selectUserFields() {
-               wfDeprecated( __METHOD__, '1.31' );
-               return [ 'user_name' ];
-       }
-
        /**
         * Return the tables, fields, and join conditions to be selected to create
         * a new revision object.
@@ -1202,7 +1005,7 @@ class Revision implements IDBAccessObject {
 
                $comment = CommentStoreComment::newUnsavedComment( $summary, null );
 
-               $title = Title::newFromID( $pageId, Title::GAID_FOR_UPDATE );
+               $title = Title::newFromID( $pageId, Title::READ_LATEST );
                if ( $title === null ) {
                        return null;
                }
index ff9ac57..759180a 100644 (file)
@@ -531,8 +531,6 @@ abstract class RevisionRecord {
                                $text = $title->getPrefixedText();
                                wfDebug( "Checking for $permissionlist on $text due to $field match on $bitfield\n" );
 
-                               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
-
                                foreach ( $permissions as $perm ) {
                                        if ( $permissionManager->userCan( $perm, $user, $title ) ) {
                                                return true;
index 73f622a..735a212 100644 (file)
@@ -326,10 +326,10 @@ class RevisionStore
 
                $canUseTitleNewFromId = ( $pageId !== null && $pageId > 0 && $this->dbDomain === false );
                list( $dbMode, $dbOptions ) = DBAccessObjectUtils::getDBOptions( $queryFlags );
-               $titleFlags = ( $dbMode == DB_MASTER ? Title::GAID_FOR_UPDATE : 0 );
 
                // Loading by ID is best, but Title::newFromID does not support that for foreign IDs.
                if ( $canUseTitleNewFromId ) {
+                       $titleFlags = ( $dbMode == DB_MASTER ? Title::READ_LATEST : 0 );
                        // TODO: better foreign title handling (introduce TitleFactory)
                        $title = Title::newFromID( $pageId, $titleFlags );
                        if ( $title ) {
index 740377c..689a98e 100644 (file)
@@ -77,9 +77,7 @@ use Wikimedia\ObjectFactory;
 
 return [
        'ActorMigration' => function ( MediaWikiServices $services ) : ActorMigration {
-               return new ActorMigration(
-                       $services->getMainConfig()->get( 'ActorTableSchemaMigrationStage' )
-               );
+               return new ActorMigration( SCHEMA_COMPAT_NEW );
        },
 
        'BadFileLookup' => function ( MediaWikiServices $services ) : BadFileLookup {
@@ -109,13 +107,10 @@ return [
        },
 
        'BlockManager' => function ( MediaWikiServices $services ) : BlockManager {
-               $context = RequestContext::getMain();
                return new BlockManager(
                        new ServiceOptions(
                                BlockManager::$constructorOptions, $services->getMainConfig()
                        ),
-                       $context->getUser(),
-                       $context->getRequest(),
                        $services->getPermissionManager()
                );
        },
@@ -547,7 +542,8 @@ return [
                        $services->getContentLanguage(),
                        AuthManager::singleton(),
                        $services->getLinkRendererFactory()->create(),
-                       $services->getNamespaceInfo()
+                       $services->getNamespaceInfo(),
+                       $services->getPermissionManager()
                );
                $factory->setLogger( LoggerFactory::getInstance( 'preferences' ) );
 
@@ -734,7 +730,8 @@ return [
                return new SpecialPageFactory(
                        new ServiceOptions(
                                SpecialPageFactory::$constructorOptions, $services->getMainConfig() ),
-                       $services->getContentLanguage()
+                       $services->getContentLanguage(),
+                       $services->getObjectFactory()
                );
        },
 
index cfb2ac1..518531a 100644 (file)
@@ -52,6 +52,17 @@ if ( ini_get( 'mbstring.func_overload' ) ) {
        die( 'MediaWiki does not support installations where mbstring.func_overload is non-zero.' );
 }
 
+// Define MW_ENTRY_POINT if it's not already, so that config code can check the
+// value without using defined()
+if ( !defined( 'MW_ENTRY_POINT' ) ) {
+       /**
+        * The entry point, which may be either the script filename without the
+        * file extension, or "cli" for maintenance scripts, or "unknown" for any
+        * entry point that does not set the constant.
+        */
+       define( 'MW_ENTRY_POINT', 'unknown' );
+}
+
 // Start the autoloader, so that extensions can derive classes from core files
 require_once "$IP/includes/AutoLoader.php";
 
@@ -797,22 +808,17 @@ if ( !defined( 'MW_NO_SESSION' ) && !$wgCommandLineMode ) {
        // Initialize the session
        try {
                $session = MediaWiki\Session\SessionManager::getGlobalSession();
-       } catch ( OverflowException $ex ) {
-               if ( isset( $ex->sessionInfos ) && count( $ex->sessionInfos ) >= 2 ) {
-                       // The exception is because the request had multiple possible
-                       // sessions tied for top priority. Report this to the user.
-                       $list = [];
-                       foreach ( $ex->sessionInfos as $info ) {
-                               $list[] = $info->getProvider()->describe( $wgContLang );
-                       }
-                       $list = $wgContLang->listToText( $list );
-                       throw new HttpError( 400,
-                               Message::newFromKey( 'sessionmanager-tie', $list )->inLanguage( $wgContLang )->plain()
-                       );
+       } catch ( MediaWiki\Session\SessionOverflowException $ex ) {
+               // The exception is because the request had multiple possible
+               // sessions tied for top priority. Report this to the user.
+               $list = [];
+               foreach ( $ex->getSessionInfos() as $info ) {
+                       $list[] = $info->getProvider()->describe( $wgContLang );
                }
-
-               // Not the one we want, rethrow
-               throw $ex;
+               $list = $wgContLang->listToText( $list );
+               throw new HttpError( 400,
+                       Message::newFromKey( 'sessionmanager-tie', $list )->inLanguage( $wgContLang )->plain()
+               );
        }
 
        if ( $session->isPersistent() ) {
index 4903cf0..b2c003a 100644 (file)
@@ -1531,7 +1531,9 @@ class DerivedPageDataUpdater implements IDBAccessObject, LoggerAwareInterface {
                if ( $this->options['changed']
                        && $title->getNamespace() == NS_USER_TALK
                        && $shortTitle != $legacyUser->getTitleKey()
-                       && !( $this->revision->isMinor() && $legacyUser->isAllowed( 'nominornewtalk' ) )
+                       && !( $this->revision->isMinor() && MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $legacyUser, 'nominornewtalk' ) )
                ) {
                        $recipient = User::newFromName( $shortTitle, false );
                        if ( !$recipient ) {
index 2ad42e5..2afd651 100644 (file)
  */
 class StreamFile {
        // Do not send any HTTP headers unless requested by caller (e.g. body only)
+       /** @deprecated since 1.34 */
        const STREAM_HEADLESS = HTTPFileStreamer::STREAM_HEADLESS;
        // Do not try to tear down any PHP output buffers
+       /** @deprecated since 1.34 */
        const STREAM_ALLOW_OB = HTTPFileStreamer::STREAM_ALLOW_OB;
 
        /**
@@ -105,7 +107,6 @@ class StreamFile {
                                case 'png':
                                        return 'image/png';
                                case 'jpg':
-                                       return 'image/jpeg';
                                case 'jpeg':
                                        return 'image/jpeg';
                        }
index 1e93c44..bdff7a7 100644 (file)
@@ -1059,7 +1059,7 @@ class Title implements LinkTarget, IDBAccessObject {
                        $this->lazyFillContentModel( $this->loadFieldFromDB( 'page_content_model', $flags ) );
                } elseif (
                        ( !$this->mContentModel || $flags & self::GAID_FOR_UPDATE ) &&
-                       $this->getArticleId( $flags )
+                       $this->getArticleID( $flags )
                ) {
                        $linkCache = MediaWikiServices::getInstance()->getLinkCache();
                        $linkCache->addLinkObj( $this ); # in case we already had an article ID
@@ -4270,12 +4270,21 @@ class Title implements LinkTarget, IDBAccessObject {
         * on the number of links. Typically called on create and delete.
         */
        public function touchLinks() {
-               DeferredUpdates::addUpdate( new HTMLCacheUpdate( $this, 'pagelinks', 'page-touch' ) );
+               $jobs = [];
+               $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+                       $this,
+                       'pagelinks',
+                       [ 'causeAction' => 'page-touch' ]
+               );
                if ( $this->mNamespace == NS_CATEGORY ) {
-                       DeferredUpdates::addUpdate(
-                               new HTMLCacheUpdate( $this, 'categorylinks', 'category-touch' )
+                       $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+                               $this,
+                               'categorylinks',
+                               [ 'causeAction' => 'category-touch' ]
                        );
                }
+
+               JobQueueGroup::singleton()->lazyPush( $jobs );
        }
 
        /**
index db874f2..6a61045 100644 (file)
@@ -433,27 +433,30 @@ class HistoryAction extends FormlessAction {
         * @return FeedItem
         */
        function feedItem( $row ) {
-               $rev = new Revision( $row, 0, $this->getTitle() );
-
+               $revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
+               $rev = $revisionStore->newRevisionFromRow( $row, 0, $this->getTitle() );
+               $prevRev = $revisionStore->getPreviousRevision( $rev );
+               $revComment = $rev->getComment() === null ? null : $rev->getComment()->text;
                $text = FeedUtils::formatDiffRow(
                        $this->getTitle(),
-                       $this->getTitle()->getPreviousRevisionID( $rev->getId() ),
+                       $prevRev ? $prevRev->getId() : false,
                        $rev->getId(),
                        $rev->getTimestamp(),
-                       $rev->getComment()
+                       $revComment
                );
-               if ( $rev->getComment() == '' ) {
+               $revUserText = $rev->getUser() ? $rev->getUser()->getName() : '';
+               if ( $revComment == '' ) {
                        $contLang = MediaWikiServices::getInstance()->getContentLanguage();
                        $title = $this->msg( 'history-feed-item-nocomment',
-                               $rev->getUserText(),
+                               $revUserText,
                                $contLang->timeanddate( $rev->getTimestamp() ),
                                $contLang->date( $rev->getTimestamp() ),
                                $contLang->time( $rev->getTimestamp() )
                        )->inContentLanguage()->text();
                } else {
-                       $title = $rev->getUserText() .
+                       $title = $revUserText .
                                $this->msg( 'colon-separator' )->inContentLanguage()->text() .
-                               FeedItem::stripComment( $rev->getComment() );
+                               FeedItem::stripComment( $revComment );
                }
 
                return new FeedItem(
@@ -461,7 +464,7 @@ class HistoryAction extends FormlessAction {
                        $text,
                        $this->getTitle()->getFullURL( 'diff=' . $rev->getId() . '&oldid=prev' ),
                        $rev->getTimestamp(),
-                       $rev->getUserText(),
+                       $revUserText,
                        $this->getTitle()->getTalkPage()->getFullURL()
                );
        }
index 7bcfc88..9a8949f 100644 (file)
@@ -280,11 +280,10 @@ class InfoAction extends FormlessAction {
                // Language in which the page content is (supposed to be) written
                $pageLang = $title->getPageLanguage()->getCode();
 
-               $permissionManager = $services->getPermissionManager();
-
                $pageLangHtml = $pageLang . ' - ' .
                        Language::fetchLanguageName( $pageLang, $lang->getCode() );
                // Link to Special:PageLanguage with pre-filled page title if user has permissions
+               $permissionManager = $services->getPermissionManager();
                if ( $config->get( 'PageLanguageUseDB' )
                        && $permissionManager->userCan( 'pagelang', $user, $title )
                ) {
@@ -344,8 +343,7 @@ class InfoAction extends FormlessAction {
                ];
 
                $unwatchedPageThreshold = $config->get( 'UnwatchedPageThreshold' );
-               if (
-                       $services->getPermissionManager()->userHasRight( $user, 'unwatchedpages' ) ||
+               if ( $permissionManager->userHasRight( $user, 'unwatchedpages' ) ||
                        ( $unwatchedPageThreshold !== false &&
                                $pageCounts['watchers'] >= $unwatchedPageThreshold )
                ) {
@@ -360,7 +358,7 @@ class InfoAction extends FormlessAction {
                        ) {
                                $minToDisclose = $config->get( 'UnwatchedPageSecret' );
                                if ( $pageCounts['visitingWatchers'] > $minToDisclose ||
-                                       $services->getPermissionManager()->userHasRight( $user, 'unwatchedpages' ) ) {
+                                       $permissionManager->userHasRight( $user, 'unwatchedpages' ) ) {
                                        $pageInfo['header-basic'][] = [
                                                $this->msg( 'pageinfo-visiting-watchers' ),
                                                $lang->formatNum( $pageCounts['visitingWatchers'] )
@@ -743,8 +741,6 @@ class InfoAction extends FormlessAction {
                        self::getCacheKey( $cache, $page->getTitle(), $page->getLatest() ),
                        WANObjectCache::TTL_WEEK,
                        function ( $oldValue, &$ttl, &$setOpts ) use ( $page, $config, $fname, $services ) {
-                               global $wgActorTableSchemaMigrationStage;
-
                                $title = $page->getTitle();
                                $id = $title->getArticleID();
 
@@ -752,19 +748,11 @@ class InfoAction extends FormlessAction {
                                $dbrWatchlist = wfGetDB( DB_REPLICA, 'watchlist' );
                                $setOpts += Database::getCacheSetOptions( $dbr, $dbrWatchlist );
 
-                               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                                       $tables = [ 'revision_actor_temp' ];
-                                       $field = 'revactor_actor';
-                                       $pageField = 'revactor_page';
-                                       $tsField = 'revactor_timestamp';
-                                       $joins = [];
-                               } else {
-                                       $tables = [ 'revision' ];
-                                       $field = 'rev_user_text';
-                                       $pageField = 'rev_page';
-                                       $tsField = 'rev_timestamp';
-                                       $joins = [];
-                               }
+                               $tables = [ 'revision_actor_temp' ];
+                               $field = 'revactor_actor';
+                               $pageField = 'revactor_page';
+                               $tsField = 'revactor_timestamp';
+                               $joins = [];
 
                                $watchedItemStore = $services->getWatchedItemStore();
 
index 8fd4e0a..0586e09 100644 (file)
@@ -238,23 +238,31 @@ class RawAction extends FormlessAction {
         */
        public function getOldId() {
                $oldid = $this->getRequest()->getInt( 'oldid' );
+               $rl = MediaWikiServices::getInstance()->getRevisionLookup();
                switch ( $this->getRequest()->getText( 'direction' ) ) {
                        case 'next':
                                # output next revision, or nothing if there isn't one
-                               $nextid = 0;
+                               $nextRev = null;
                                if ( $oldid ) {
-                                       $nextid = $this->getTitle()->getNextRevisionID( $oldid );
+                                       $oldRev = $rl->getRevisionById( $oldid );
+                                       if ( $oldRev ) {
+                                               $nextRev = $rl->getNextRevision( $oldRev );
+                                       }
                                }
-                               $oldid = $nextid ?: -1;
+                               $oldid = $nextRev ? $nextRev->getId() : -1;
                                break;
                        case 'prev':
                                # output previous revision, or nothing if there isn't one
+                               $prevRev = null;
                                if ( !$oldid ) {
                                        # get the current revision so we can get the penultimate one
                                        $oldid = $this->page->getLatest();
                                }
-                               $previd = $this->getTitle()->getPreviousRevisionID( $oldid );
-                               $oldid = $previd ?: -1;
+                               $oldRev = $rl->getRevisionById( $oldid );
+                               if ( $oldRev ) {
+                                       $prevRev = $rl->getPreviousRevision( $oldRev );
+                               }
+                               $oldid = $prevRev ? $prevRev->getId() : -1;
                                break;
                        case 'cur':
                                $oldid = 0;
index fdf9cf1..06f6f60 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  */
 
+use MediaWiki\MediaWikiServices;
 use MediaWiki\Storage\RevisionRecord;
 
 /**
@@ -239,11 +240,15 @@ class ApiEditPage extends ApiBase {
                        $params['text'] = $newContent->serialize( $contentFormat );
                        // If no summary was given and we only undid one rev,
                        // use an autosummary
-                       if ( is_null( $params['summary'] ) &&
-                               $titleObj->getNextRevisionID( $undoafterRev->getId() ) == $params['undo']
-                       ) {
-                               $params['summary'] = wfMessage( 'undo-summary' )
-                                       ->params( $params['undo'], $undoRev->getUserText() )->inContentLanguage()->text();
+
+                       if ( is_null( $params['summary'] ) ) {
+                               $nextRev = MediaWikiServices::getInstance()->getRevisionLookup()
+                                       ->getNextRevision( $undoafterRev->getRevisionRecord() );
+                               if ( $nextRev && $nextRev->getId() == $params['undo'] ) {
+                                       $params['summary'] = wfMessage( 'undo-summary' )
+                                               ->params( $params['undo'], $undoRev->getUserText() )
+                                               ->inContentLanguage()->text();
+                               }
                        }
                }
 
index f0e0077..7bbce97 100644 (file)
@@ -281,7 +281,10 @@ class ApiMain extends ApiBase {
                }
                $this->mResult->setErrorFormatter( $this->getErrorFormatter() );
 
-               $this->mModuleMgr = new ApiModuleManager( $this );
+               $this->mModuleMgr = new ApiModuleManager(
+                       $this,
+                       MediaWikiServices::getInstance()->getObjectFactory()
+               );
                $this->mModuleMgr->addModules( self::$Modules, 'action' );
                $this->mModuleMgr->addModules( $config->get( 'APIModules' ), 'action' );
                $this->mModuleMgr->addModules( self::$Formats, 'format' );
index d2df013..8d5a82b 100644 (file)
@@ -21,6 +21,9 @@
  * @since 1.21
  */
 
+use MediaWiki\MediaWikiServices;
+use Wikimedia\ObjectFactory;
+
 /**
  * This class holds a list of modules and handles instantiation
  *
@@ -45,64 +48,35 @@ class ApiModuleManager extends ContextSource {
         * @var array[]
         */
        private $mModules = [];
+       /**
+        * @var ObjectFactory
+        */
+       private $objectFactory;
 
        /**
         * Construct new module manager
+        *
         * @param ApiBase $parentModule Parent module instance will be used during instantiation
+        * @param ObjectFactory|null $objectFactory Object factory to use when instantiating modules
         */
-       public function __construct( ApiBase $parentModule ) {
+       public function __construct( ApiBase $parentModule, ObjectFactory $objectFactory = null ) {
                $this->mParent = $parentModule;
+               $this->objectFactory = $objectFactory ?? MediaWikiServices::getInstance()->getObjectFactory();
        }
 
        /**
         * Add a list of modules to the manager. Each module is described
-        * by a module spec.
-        *
-        * Each module spec is an associative array containing at least
-        * the 'class' key for the module's class, and optionally a
-        * 'factory' key for the factory function to use for the module.
+        * by an ObjectFactory spec.
         *
-        * That factory function will be called with two parameters,
-        * the parent module (an instance of ApiBase, usually ApiMain)
-        * and the name the module was registered under. The return
-        * value must be an instance of the class given in the 'class'
-        * field.
+        * This simply calls `addModule()` for each module in `$modules`.
         *
-        * For backward compatibility, the module spec may also be a
-        * simple string containing the module's class name. In that
-        * case, the class' constructor will be called with the parent
-        * module and module name as parameters, as described above.
-        *
-        * Examples for defining module specs:
-        *
-        * @code
-        *  $modules['foo'] = 'ApiFoo';
-        *  $modules['bar'] = [
-        *      'class' => ApiBar::class,
-        *      'factory' => function( $main, $name ) { ... }
-        *  ];
-        *  $modules['xyzzy'] = [
-        *      'class' => ApiXyzzy::class,
-        *      'factory' => [ XyzzyFactory::class, 'newApiModule' ]
-        *  ];
-        * @endcode
-        *
-        * @param array $modules A map of ModuleName => ModuleSpec; The ModuleSpec
-        *        is either a string containing the module's class name, or an associative
-        *        array (see above for details).
+        * @see ApiModuleManager::addModule()
+        * @param array $modules A map of ModuleName => ModuleSpec
         * @param string $group Which group modules belong to (action,format,...)
         */
        public function addModules( array $modules, $group ) {
                foreach ( $modules as $name => $moduleSpec ) {
-                       if ( is_array( $moduleSpec ) ) {
-                               $class = $moduleSpec['class'];
-                               $factory = ( $moduleSpec['factory'] ?? null );
-                       } else {
-                               $class = $moduleSpec;
-                               $factory = null;
-                       }
-
-                       $this->addModule( $name, $group, $class, $factory );
+                       $this->addModule( $name, $group, $moduleSpec );
                }
        }
 
@@ -111,14 +85,21 @@ class ApiModuleManager extends ContextSource {
         * classes who wish to add their own modules to their lexicon or override the
         * behavior of inherent ones.
         *
+        * ObjectFactory is used to instantiate the module when needed. The parent module
+        * (`$parentModule` from `__construct()`) and the `$name` are passed as extraArgs.
+        *
+        * @since 1.34, accepts an ObjectFactory spec as the third parameter. The old calling convention,
+        *  passing a class name as parameter #3 and an optional factory callable as parameter #4, is
+        *  deprecated.
         * @param string $name The identifier for this module.
         * @param string $group Name of the module group
-        * @param string $class The class where this module is implemented.
-        * @param callable|null $factory Callback for instantiating the module.
+        * @param string|array $spec The ObjectFactory spec for instantiating the module,
+        *  or a class name to instantiate.
+        * @param callable|null $factory Callback for instantiating the module (deprecated).
         *
         * @throws InvalidArgumentException
         */
-       public function addModule( $name, $group, $class, $factory = null ) {
+       public function addModule( $name, $group, $spec, $factory = null ) {
                if ( !is_string( $name ) ) {
                        throw new InvalidArgumentException( '$name must be a string' );
                }
@@ -127,16 +108,23 @@ class ApiModuleManager extends ContextSource {
                        throw new InvalidArgumentException( '$group must be a string' );
                }
 
-               if ( !is_string( $class ) ) {
-                       throw new InvalidArgumentException( '$class must be a string' );
-               }
+               if ( is_string( $spec ) ) {
+                       $spec = [
+                               'class' => $spec
+                       ];
 
-               if ( $factory !== null && !is_callable( $factory ) ) {
-                       throw new InvalidArgumentException( '$factory must be a callable (or null)' );
+                       if ( is_callable( $factory ) ) {
+                               wfDeprecated( __METHOD__ . ' with $class and $factory', '1.34' );
+                               $spec['factory'] = $factory;
+                       }
+               } elseif ( !is_array( $spec ) ) {
+                       throw new InvalidArgumentException( '$spec must be a string or an array' );
+               } elseif ( !isset( $spec['class'] ) ) {
+                       throw new InvalidArgumentException( '$spec must define a class name' );
                }
 
                $this->mGroups[$group] = null;
-               $this->mModules[$name] = [ $group, $class, $factory ];
+               $this->mModules[$name] = [ $group, $spec ];
        }
 
        /**
@@ -153,7 +141,7 @@ class ApiModuleManager extends ContextSource {
                        return null;
                }
 
-               list( $moduleGroup, $moduleClass, $moduleFactory ) = $this->mModules[$moduleName];
+               list( $moduleGroup, $spec ) = $this->mModules[$moduleName];
 
                if ( $group !== null && $moduleGroup !== $group ) {
                        return null;
@@ -164,7 +152,7 @@ class ApiModuleManager extends ContextSource {
                        return $this->mInstances[$moduleName];
                } else {
                        // new instance
-                       $instance = $this->instantiateModule( $moduleName, $moduleClass, $moduleFactory );
+                       $instance = $this->instantiateModule( $moduleName, $spec );
 
                        if ( !$ignoreCache ) {
                                // cache this instance in case it is needed later
@@ -179,28 +167,22 @@ class ApiModuleManager extends ContextSource {
         * Instantiate the module using the given class or factory function.
         *
         * @param string $name The identifier for this module.
-        * @param string $class The class where this module is implemented.
-        * @param callable|null $factory Callback for instantiating the module.
+        * @param array $spec The ObjectFactory spec for instantiating the module.
         *
-        * @throws MWException
+        * @throws UnexpectedValueException
         * @return ApiBase
         */
-       private function instantiateModule( $name, $class, $factory = null ) {
-               if ( $factory !== null ) {
-                       // create instance from factory
-                       $instance = call_user_func( $factory, $this->mParent, $name );
-
-                       if ( !$instance instanceof $class ) {
-                               throw new MWException(
-                                       "The factory function for module $name did not return an instance of $class!"
-                               );
-                       }
-               } else {
-                       // create instance from class name
-                       $instance = new $class( $this->mParent, $name );
-               }
-
-               return $instance;
+       private function instantiateModule( $name, $spec ) {
+               return $this->objectFactory->createObject(
+                       $spec,
+                       [
+                               'extraArgs' => [
+                                       $this->mParent,
+                                       $name
+                               ],
+                               'assertClass' => $spec['class']
+                       ]
+               );
        }
 
        /**
@@ -213,8 +195,8 @@ class ApiModuleManager extends ContextSource {
                        return array_keys( $this->mModules );
                }
                $result = [];
-               foreach ( $this->mModules as $name => $grpCls ) {
-                       if ( $grpCls[0] === $group ) {
+               foreach ( $this->mModules as $name => $groupAndSpec ) {
+                       if ( $groupAndSpec[0] === $group ) {
                                $result[] = $name;
                        }
                }
@@ -229,9 +211,9 @@ class ApiModuleManager extends ContextSource {
         */
        public function getNamesWithClasses( $group = null ) {
                $result = [];
-               foreach ( $this->mModules as $name => $grpCls ) {
-                       if ( $group === null || $grpCls[0] === $group ) {
-                               $result[$name] = $grpCls[1];
+               foreach ( $this->mModules as $name => $groupAndSpec ) {
+                       if ( $group === null || $groupAndSpec[0] === $group ) {
+                               $result[$name] = $groupAndSpec[1]['class'];
                        }
                }
 
@@ -247,7 +229,7 @@ class ApiModuleManager extends ContextSource {
         */
        public function getClassName( $module ) {
                if ( isset( $this->mModules[$module] ) ) {
-                       return $this->mModules[$module][1];
+                       return $this->mModules[$module][1]['class'];
                }
 
                return false;
index 6afb018..e68676a 100644 (file)
@@ -1166,7 +1166,8 @@ class ApiPageSet extends ApiBase {
                $services = MediaWikiServices::getInstance();
                $contLang = $services->getContentLanguage();
 
-               foreach ( $titles as $title ) {
+               $titleObjects = [];
+               foreach ( $titles as $index => $title ) {
                        if ( is_string( $title ) ) {
                                try {
                                        $titleObj = Title::newFromTextThrow( $title, $this->mDefaultNamespace );
@@ -1185,6 +1186,16 @@ class ApiPageSet extends ApiBase {
                        } else {
                                $titleObj = $title;
                        }
+
+                       $titleObjects[$index] = $titleObj;
+               }
+
+               // Get gender information
+               $genderCache = $services->getGenderCache();
+               $genderCache->doTitlesArray( $titleObjects, __METHOD__ );
+
+               foreach ( $titleObjects as $index => $titleObj ) {
+                       $title = is_string( $titles[$index] ) ? $titles[$index] : false;
                        $unconvertedTitle = $titleObj->getPrefixedText();
                        $titleWasConverted = false;
                        if ( $titleObj->isExternal() ) {
@@ -1197,7 +1208,7 @@ class ApiPageSet extends ApiBase {
                                ) {
                                        // Language::findVariantLink will modify titleText and titleObj into
                                        // the canonical variant if possible
-                                       $titleText = is_string( $title ) ? $title : $titleObj->getPrefixedText();
+                                       $titleText = $title !== false ? $title : $titleObj->getPrefixedText();
                                        $contLang->findVariantLink( $titleText, $titleObj );
                                        $titleWasConverted = $unconvertedTitle !== $titleObj->getPrefixedText();
                                }
@@ -1245,24 +1256,13 @@ class ApiPageSet extends ApiBase {
                        if ( $titleWasConverted ) {
                                $this->mConvertedTitles[$unconvertedTitle] = $titleObj->getPrefixedText();
                                // In this case the page can't be Special.
-                               if ( is_string( $title ) && $title !== $unconvertedTitle ) {
+                               if ( $title !== false && $title !== $unconvertedTitle ) {
                                        $this->mNormalizedTitles[$title] = $unconvertedTitle;
                                }
-                       } elseif ( is_string( $title ) && $title !== $titleObj->getPrefixedText() ) {
+                       } elseif ( $title !== false && $title !== $titleObj->getPrefixedText() ) {
                                $this->mNormalizedTitles[$title] = $titleObj->getPrefixedText();
                        }
-
-                       // Need gender information
-                       if (
-                               $services->getNamespaceInfo()->
-                                       hasGenderDistinction( $titleObj->getNamespace() )
-                       ) {
-                               $usernames[] = $titleObj->getText();
-                       }
                }
-               // Get gender information
-               $genderCache = $services->getGenderCache();
-               $genderCache->doQuery( $usernames, __METHOD__ );
 
                return $linkBatch;
        }
index c78e445..a7ff729 100644 (file)
@@ -20,6 +20,7 @@
  * @file
  */
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\Rdbms\IDatabase;
 
 /**
@@ -134,7 +135,10 @@ class ApiQuery extends ApiBase {
        public function __construct( ApiMain $main, $action ) {
                parent::__construct( $main, $action );
 
-               $this->mModuleMgr = new ApiModuleManager( $this );
+               $this->mModuleMgr = new ApiModuleManager(
+                       $this,
+                       MediaWikiServices::getInstance()->getObjectFactory()
+               );
 
                // Allow custom modules to be added in LocalSettings.php
                $config = $this->getConfig();
index 7d6d342..2a49984 100644 (file)
@@ -43,9 +43,6 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
         * @return void
         */
        protected function run( ApiPageSet $resultPageSet = null ) {
-               // Before doing anything at all, let's check permissions
-               $this->checkUserRightsAny( 'deletedhistory' );
-
                $user = $this->getUser();
                $db = $this->getDB();
                $params = $this->extractRequestParams( false );
@@ -144,8 +141,15 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
                }
 
                // This means stricter restrictions
-               if ( $this->fetchContent ) {
-                       $this->checkUserRightsAny( [ 'deletedtext', 'undelete' ] );
+               if ( ( $this->fld_comment || $this->fld_parsedcomment ) &&
+                       !$this->getPermissionManager()->userHasRight( $user, 'deletedhistory' )
+               ) {
+                       $this->dieWithError( 'apierror-cantview-deleted-comment', 'permissiondenied' );
+               }
+               if ( $this->fetchContent &&
+                       !$this->getPermissionManager()->userHasAnyRight( $user, 'deletedtext', 'undelete' )
+               ) {
+                       $this->dieWithError( 'apierror-cantview-deleted-revision-content', 'permissiondenied' );
                }
 
                $miser_ns = null;
@@ -235,8 +239,6 @@ class ApiQueryAllDeletedRevisions extends ApiQueryRevisionsBase {
 
                if ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ) {
                        // Paranoia: avoid brute force searches (T19342)
-                       // (shouldn't be able to get here without 'deletedhistory', but
-                       // check it again just in case)
                        if ( !$this->getPermissionManager()->userHasRight( $user, 'deletedhistory' ) ) {
                                $bitmask = RevisionRecord::DELETED_USER;
                        } elseif ( !$this->getPermissionManager()
index 3751102..3d4c49b 100644 (file)
@@ -40,8 +40,6 @@ class ApiQueryAllRevisions extends ApiQueryRevisionsBase {
         * @return void
         */
        protected function run( ApiPageSet $resultPageSet = null ) {
-               global $wgActorTableSchemaMigrationStage;
-
                $db = $this->getDB();
                $params = $this->extractRequestParams( false );
                $services = MediaWikiServices::getInstance();
@@ -54,9 +52,7 @@ class ApiQueryAllRevisions extends ApiQueryRevisionsBase {
                $tsField = 'rev_timestamp';
                $idField = 'rev_id';
                $pageField = 'rev_page';
-               if ( $params['user'] !== null &&
-                       ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW )
-               ) {
+               if ( $params['user'] !== null ) {
                        // The query is probably best done using the actor_timestamp index on
                        // revision_actor_temp. Use the denormalized fields from that table.
                        $tsField = 'revactor_timestamp';
index e0513e2..a7d4fb9 100644 (file)
@@ -41,8 +41,6 @@ class ApiQueryAllUsers extends ApiQueryBase {
        }
 
        public function execute() {
-               global $wgActorTableSchemaMigrationStage;
-
                $params = $this->extractRequestParams();
                $activeUserDays = $this->getConfig()->get( 'ActiveUserDays' );
 
@@ -181,22 +179,17 @@ class ApiQueryAllUsers extends ApiQueryBase {
                        ] ] );
 
                        // Actually count the actions using a subquery (T66505 and T66507)
-                       $tables = [ 'recentchanges' ];
-                       $joins = [];
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_OLD ) {
-                               $userCond = 'rc_user_text = user_name';
-                       } else {
-                               $tables[] = 'actor';
-                               $joins['actor'] = [ 'JOIN', 'rc_actor = actor_id' ];
-                               $userCond = 'actor_user = user_id';
-                       }
+                       $tables = [ 'recentchanges', 'actor' ];
+                       $joins = [
+                               'actor' => [ 'JOIN', 'rc_actor = actor_id' ],
+                       ];
                        $timestamp = $db->timestamp( wfTimestamp( TS_UNIX ) - $activeUserSeconds );
                        $this->addFields( [
                                'recentactions' => '(' . $db->selectSQLText(
                                        $tables,
                                        'COUNT(*)',
                                        [
-                                               $userCond,
+                                               'actor_user = user_id',
                                                'rc_type != ' . $db->addQuotes( RC_EXTERNAL ), // no wikidata
                                                'rc_log_type IS NULL OR rc_log_type != ' . $db->addQuotes( 'newusers' ),
                                                'rc_timestamp >= ' . $db->addQuotes( $timestamp ),
index a1945c4..f2e306f 100644 (file)
@@ -46,8 +46,6 @@ class ApiQueryContributors extends ApiQueryBase {
        }
 
        public function execute() {
-               global $wgActorTableSchemaMigrationStage;
-
                $db = $this->getDB();
                $params = $this->extractRequestParams();
                $this->requireMaxOneParameter( $params, 'group', 'excludegroup', 'rights', 'excluderights' );
@@ -80,14 +78,10 @@ class ApiQueryContributors extends ApiQueryBase {
                $result = $this->getResult();
                $revQuery = MediaWikiServices::getInstance()->getRevisionStore()->getQueryInfo();
 
-               // For SCHEMA_COMPAT_READ_NEW, target indexes on the
-               // revision_actor_temp table, otherwise on the revision table.
-               $pageField = ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW )
-                       ? 'revactor_page' : 'rev_page';
-               $idField = ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW )
-                       ? 'revactor_actor' : $revQuery['fields']['rev_user'];
-               $countField = ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW )
-                       ? 'revactor_actor' : $revQuery['fields']['rev_user_text'];
+               // Target indexes on the revision_actor_temp table.
+               $pageField = 'revactor_page';
+               $idField = 'revactor_actor';
+               $countField = 'revactor_actor';
 
                // First, count anons
                $this->addTables( $revQuery['tables'] );
index fc88499..12fd20a 100644 (file)
@@ -40,8 +40,6 @@ class ApiQueryDeletedRevisions extends ApiQueryRevisionsBase {
 
        protected function run( ApiPageSet $resultPageSet = null ) {
                $user = $this->getUser();
-               // Before doing anything at all, let's check permissions
-               $this->checkUserRightsAny( 'deletedhistory' );
 
                $pageSet = $this->getPageSet();
                $pageMap = $pageSet->getGoodAndMissingTitlesByNamespace();
@@ -95,8 +93,15 @@ class ApiQueryDeletedRevisions extends ApiQueryRevisionsBase {
                }
 
                // This means stricter restrictions
-               if ( $this->fetchContent ) {
-                       $this->checkUserRightsAny( [ 'deletedtext', 'undelete' ] );
+               if ( ( $this->fld_comment || $this->fld_parsedcomment ) &&
+                       !$this->getPermissionManager()->userHasRight( $user, 'deletedhistory' )
+               ) {
+                       $this->dieWithError( 'apierror-cantview-deleted-comment', 'permissiondenied' );
+               }
+               if ( $this->fetchContent &&
+                       !$this->getPermissionManager()->userHasAnyRight( $user, 'deletedtext', 'undelete' )
+               ) {
+                       $this->dieWithError( 'apierror-cantview-deleted-revision-content', 'permissiondenied' );
                }
 
                $dir = $params['dir'];
@@ -130,8 +135,6 @@ class ApiQueryDeletedRevisions extends ApiQueryRevisionsBase {
 
                if ( !is_null( $params['user'] ) || !is_null( $params['excludeuser'] ) ) {
                        // Paranoia: avoid brute force searches (T19342)
-                       // (shouldn't be able to get here without 'deletedhistory', but
-                       // check it again just in case)
                        if ( !$this->getPermissionManager()->userHasRight( $user, 'deletedhistory' ) ) {
                                $bitmask = RevisionRecord::DELETED_USER;
                        } elseif ( !$this->getPermissionManager()
index f9087eb..c84f457 100644 (file)
@@ -38,9 +38,6 @@ class ApiQueryFilearchive extends ApiQueryBase {
        }
 
        public function execute() {
-               // Before doing anything at all, let's check permissions
-               $this->checkUserRightsAny( 'deletedhistory' );
-
                $user = $this->getUser();
                $db = $this->getDB();
                $commentStore = CommentStore::getStore();
@@ -60,6 +57,17 @@ class ApiQueryFilearchive extends ApiQueryBase {
                $fld_bitdepth = isset( $prop['bitdepth'] );
                $fld_archivename = isset( $prop['archivename'] );
 
+               if ( $fld_description &&
+                       !$this->getPermissionManager()->userHasRight( $user, 'deletedhistory' )
+               ) {
+                       $this->dieWithError( 'apierror-cantview-deleted-description', 'permissiondenied' );
+               }
+               if ( $fld_metadata &&
+                       !$this->getPermissionManager()->userHasAnyRight( $user, 'deletedtext', 'undelete' )
+               ) {
+                       $this->dieWithError( 'apierror-cantview-deleted-metadata', 'permissiondenied' );
+               }
+
                $fileQuery = ArchivedFile::getQueryInfo();
                $this->addTables( $fileQuery['tables'] );
                $this->addFields( $fileQuery['fields'] );
@@ -110,23 +118,22 @@ class ApiQueryFilearchive extends ApiQueryBase {
                        }
                        if ( $sha1 ) {
                                $this->addWhereFld( 'fa_sha1', $sha1 );
+                               // Paranoia: avoid brute force searches (T19342)
+                               if ( !$this->getPermissionManager()->userHasRight( $user, 'deletedtext' ) ) {
+                                       $bitmask = File::DELETED_FILE;
+                               } elseif ( !$this->getPermissionManager()
+                                       ->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' )
+                               ) {
+                                       $bitmask = File::DELETED_FILE | File::DELETED_RESTRICTED;
+                               } else {
+                                       $bitmask = 0;
+                               }
+                               if ( $bitmask ) {
+                                       $this->addWhere( $this->getDB()->bitAnd( 'fa_deleted', $bitmask ) . " != $bitmask" );
+                               }
                        }
                }
 
-               // Exclude files this user can't view.
-               if ( !$this->getPermissionManager()->userHasRight( $user, 'deletedtext' ) ) {
-                       $bitmask = File::DELETED_FILE;
-               } elseif ( !$this->getPermissionManager()
-                       ->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' )
-               ) {
-                       $bitmask = File::DELETED_FILE | File::DELETED_RESTRICTED;
-               } else {
-                       $bitmask = 0;
-               }
-               if ( $bitmask ) {
-                       $this->addWhere( $this->getDB()->bitAnd( 'fa_deleted', $bitmask ) . " != $bitmask" );
-               }
-
                $limit = $params['limit'];
                $this->addOption( 'LIMIT', $limit + 1 );
                $sort = ( $params['dir'] == 'descending' ? ' DESC' : '' );
@@ -150,6 +157,8 @@ class ApiQueryFilearchive extends ApiQueryBase {
                                break;
                        }
 
+                       $canViewFile = RevisionRecord::userCanBitfield( $row->fa_deleted, File::DELETED_FILE, $user );
+
                        $file = [];
                        $file['id'] = (int)$row->fa_id;
                        $file['name'] = $row->fa_name;
@@ -171,13 +180,13 @@ class ApiQueryFilearchive extends ApiQueryBase {
                                $file['userid'] = (int)$row->fa_user;
                                $file['user'] = $row->fa_user_text;
                        }
-                       if ( $fld_sha1 ) {
+                       if ( $fld_sha1 && $canViewFile ) {
                                $file['sha1'] = Wikimedia\base_convert( $row->fa_sha1, 36, 16, 40 );
                        }
                        if ( $fld_timestamp ) {
                                $file['timestamp'] = wfTimestamp( TS_ISO_8601, $row->fa_timestamp );
                        }
-                       if ( $fld_size || $fld_dimensions ) {
+                       if ( ( $fld_size || $fld_dimensions ) && $canViewFile ) {
                                $file['size'] = $row->fa_size;
 
                                $pageCount = ArchivedFile::newFromRow( $row )->pageCount();
@@ -188,18 +197,18 @@ class ApiQueryFilearchive extends ApiQueryBase {
                                $file['height'] = $row->fa_height;
                                $file['width'] = $row->fa_width;
                        }
-                       if ( $fld_mediatype ) {
+                       if ( $fld_mediatype && $canViewFile ) {
                                $file['mediatype'] = $row->fa_media_type;
                        }
-                       if ( $fld_metadata ) {
+                       if ( $fld_metadata && $canViewFile ) {
                                $file['metadata'] = $row->fa_metadata
                                        ? ApiQueryImageInfo::processMetaData( unserialize( $row->fa_metadata ), $result )
                                        : null;
                        }
-                       if ( $fld_bitdepth ) {
+                       if ( $fld_bitdepth && $canViewFile ) {
                                $file['bitdepth'] = $row->fa_bits;
                        }
-                       if ( $fld_mime ) {
+                       if ( $fld_mime && $canViewFile ) {
                                $file['mime'] = "$row->fa_major_mime/$row->fa_minor_mime";
                        }
                        if ( $fld_archivename && !is_null( $row->fa_archive_name ) ) {
index d616ad4..5b2b1b7 100644 (file)
@@ -85,8 +85,6 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase {
        }
 
        protected function run( ApiPageSet $resultPageSet = null ) {
-               global $wgActorTableSchemaMigrationStage;
-
                $params = $this->extractRequestParams( false );
                $revisionStore = MediaWikiServices::getInstance()->getRevisionStore();
 
@@ -137,9 +135,7 @@ class ApiQueryRevisions extends ApiQueryRevisionsBase {
                $idField = 'rev_id';
                $tsField = 'rev_timestamp';
                $pageField = 'rev_page';
-               if ( $params['user'] !== null &&
-                       ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW )
-               ) {
+               if ( $params['user'] !== null ) {
                        // We're going to want to use the page_actor_timestamp index (on revision_actor_temp)
                        // so use that table's denormalized fields.
                        $idField = 'revactor_rev';
index 1924ca0..c84de8c 100644 (file)
@@ -70,11 +70,37 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
                }
        }
 
-       private $propertyFilter = [
+       private static $propertyFilter = [
                'user', 'userid', 'comment', 'parsedcomment',
                'mediatype', 'archivename', 'uploadwarning',
        ];
 
+       /**
+        * Returns all possible parameters to siiprop
+        *
+        * @param array|null $filter List of properties to filter out
+        * @return array
+        */
+       public static function getPropertyNames( $filter = null ) {
+               if ( $filter === null ) {
+                       $filter = self::$propertyFilter;
+               }
+               return parent::getPropertyNames( $filter );
+       }
+
+       /**
+        * Returns messages for all possible parameters to siiprop
+        *
+        * @param array|null $filter List of properties to filter out
+        * @return array
+        */
+       public static function getPropertyMessages( $filter = null ) {
+               if ( $filter === null ) {
+                       $filter = self::$propertyFilter;
+               }
+               return parent::getPropertyMessages( $filter );
+       }
+
        public function getAllowedParams() {
                return [
                        'filekey' => [
@@ -87,9 +113,9 @@ class ApiQueryStashImageInfo extends ApiQueryImageInfo {
                        'prop' => [
                                ApiBase::PARAM_ISMULTI => true,
                                ApiBase::PARAM_DFLT => 'timestamp|url',
-                               ApiBase::PARAM_TYPE => self::getPropertyNames( $this->propertyFilter ),
+                               ApiBase::PARAM_TYPE => self::getPropertyNames(),
                                ApiBase::PARAM_HELP_MSG => 'apihelp-query+imageinfo-param-prop',
-                               ApiBase::PARAM_HELP_MSG_PER_VALUE => self::getPropertyMessages( $this->propertyFilter )
+                               ApiBase::PARAM_HELP_MSG_PER_VALUE => self::getPropertyMessages()
                        ],
                        'urlwidth' => [
                                ApiBase::PARAM_TYPE => 'integer',
index 919c763..189f957 100644 (file)
@@ -42,8 +42,6 @@ class ApiQueryUserContribs extends ApiQueryBase {
                $fld_patrolled = false, $fld_tags = false, $fld_size = false, $fld_sizediff = false;
 
        public function execute() {
-               global $wgActorTableSchemaMigrationStage;
-
                // Parse some parameters
                $this->params = $this->extractRequestParams();
 
@@ -82,8 +80,6 @@ class ApiQueryUserContribs extends ApiQueryBase {
                        // a wiki with users "Test00000001" to "Test99999999"), use a
                        // generator with batched lookup and continuation.
                        $userIter = call_user_func( function () use ( $dbSecondary, $sort, $op, $fname ) {
-                               global $wgActorTableSchemaMigrationStage;
-
                                $fromName = false;
                                if ( !is_null( $this->params['continue'] ) ) {
                                        $continue = explode( '|', $this->params['continue'] );
@@ -97,26 +93,13 @@ class ApiQueryUserContribs extends ApiQueryBase {
 
                                do {
                                        $from = $fromName ? "$op= " . $dbSecondary->addQuotes( $fromName ) : false;
-
-                                       // For the new schema, pull from the actor table. For the
-                                       // old, pull from rev_user.
-                                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                                               $res = $dbSecondary->select(
-                                                       'actor',
-                                                       [ 'actor_id', 'user_id' => 'COALESCE(actor_user,0)', 'user_name' => 'actor_name' ],
-                                                       array_merge( [ "actor_name$like" ], $from ? [ "actor_name $from" ] : [] ),
-                                                       $fname,
-                                                       [ 'ORDER BY' => [ "user_name $sort" ], 'LIMIT' => $limit ]
-                                               );
-                                       } else {
-                                               $res = $dbSecondary->select(
-                                                       'revision',
-                                                       [ 'actor_id' => 'NULL', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
-                                                       array_merge( [ "rev_user_text$like" ], $from ? [ "rev_user_text $from" ] : [] ),
-                                                       $fname,
-                                                       [ 'DISTINCT', 'ORDER BY' => [ "rev_user_text $sort" ], 'LIMIT' => $limit ]
-                                               );
-                                       }
+                                       $res = $dbSecondary->select(
+                                               'actor',
+                                               [ 'actor_id', 'user_id' => 'COALESCE(actor_user,0)', 'user_name' => 'actor_name' ],
+                                               array_merge( [ "actor_name$like" ], $from ? [ "actor_name $from" ] : [] ),
+                                               $fname,
+                                               [ 'ORDER BY' => [ "user_name $sort" ], 'LIMIT' => $limit ]
+                                       );
 
                                        $count = 0;
                                        $fromName = false;
@@ -159,25 +142,13 @@ class ApiQueryUserContribs extends ApiQueryBase {
                                $from = "$op= $fromId";
                        }
 
-                       // For the new schema, just select from the actor table. For the
-                       // old, select from user.
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                               $res = $dbSecondary->select(
-                                       'actor',
-                                       [ 'actor_id', 'user_id' => 'actor_user', 'user_name' => 'actor_name' ],
-                                       array_merge( [ 'actor_user' => $ids ], $from ? [ "actor_id $from" ] : [] ),
-                                       __METHOD__,
-                                       [ 'ORDER BY' => "user_id $sort" ]
-                               );
-                       } else {
-                               $res = $dbSecondary->select(
-                                       'user',
-                                       [ 'actor_id' => 'NULL', 'user_id' => 'user_id', 'user_name' => 'user_name' ],
-                                       array_merge( [ 'user_id' => $ids ], $from ? [ "user_id $from" ] : [] ),
-                                       __METHOD__,
-                                       [ 'ORDER BY' => "user_id $sort" ]
-                               );
-                       }
+                       $res = $dbSecondary->select(
+                               'actor',
+                               [ 'actor_id', 'user_id' => 'actor_user', 'user_name' => 'actor_name' ],
+                               array_merge( [ 'actor_user' => $ids ], $from ? [ "actor_id $from" ] : [] ),
+                               __METHOD__,
+                               [ 'ORDER BY' => "user_id $sort" ]
+                       );
                        $userIter = UserArray::newFromResult( $res );
                        $batchSize = count( $ids );
                } else {
@@ -222,57 +193,22 @@ class ApiQueryUserContribs extends ApiQueryBase {
                                $from = "$op= " . $dbSecondary->addQuotes( $fromName );
                        }
 
-                       // For the new schema, just select from the actor table. For the
-                       // old, select from user then merge in any unknown users (IPs and imports).
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                               $res = $dbSecondary->select(
-                                       'actor',
-                                       [ 'actor_id', 'user_id' => 'actor_user', 'user_name' => 'actor_name' ],
-                                       array_merge( [ 'actor_name' => array_keys( $names ) ], $from ? [ "actor_id $from" ] : [] ),
-                                       __METHOD__,
-                                       [ 'ORDER BY' => "actor_name $sort" ]
-                               );
-                               $userIter = UserArray::newFromResult( $res );
-                       } else {
-                               $res = $dbSecondary->select(
-                                       'user',
-                                       [ 'actor_id' => 'NULL', 'user_id', 'user_name' ],
-                                       array_merge( [ 'user_name' => array_keys( $names ) ], $from ? [ "user_name $from" ] : [] ),
-                                       __METHOD__
-                               );
-                               foreach ( $res as $row ) {
-                                       $names[$row->user_name] = $row;
-                               }
-                               if ( $this->params['dir'] == 'newer' ) {
-                                       ksort( $names, SORT_STRING );
-                               } else {
-                                       krsort( $names, SORT_STRING );
-                               }
-                               $neg = $op === '>' ? -1 : 1;
-                               $userIter = call_user_func( function () use ( $names, $fromName, $neg ) {
-                                       foreach ( $names as $name => $row ) {
-                                               if ( $fromName === false || $neg * strcmp( $name, $fromName ) <= 0 ) {
-                                                       $user = $row ? User::newFromRow( $row ) : User::newFromName( $name, false );
-                                                       yield $user;
-                                               }
-                                       }
-                               } );
-                       }
+                       $res = $dbSecondary->select(
+                               'actor',
+                               [ 'actor_id', 'user_id' => 'actor_user', 'user_name' => 'actor_name' ],
+                               array_merge( [ 'actor_name' => array_keys( $names ) ], $from ? [ "actor_id $from" ] : [] ),
+                               __METHOD__,
+                               [ 'ORDER BY' => "actor_name $sort" ]
+                       );
+                       $userIter = UserArray::newFromResult( $res );
                        $batchSize = count( $names );
                }
 
-               // With the new schema, the DB query will order by actor so update $this->orderBy to match.
-               if ( $batchSize > 1 && ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) ) {
+               // The DB query will order by actor so update $this->orderBy to match.
+               if ( $batchSize > 1 ) {
                        $this->orderBy = 'actor';
                }
 
-               // Use the 'contributions' replica, but only if we're querying by user ID (T216656).
-               if ( $this->orderBy === 'id' &&
-                       !( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW )
-               ) {
-                       $this->selectNamedDB( 'contributions', DB_REPLICA, 'contributions' );
-               }
-
                $count = 0;
                $limit = $this->params['limit'];
                $userIter->rewind();
@@ -325,47 +261,33 @@ class ApiQueryUserContribs extends ApiQueryBase {
         * @param int $limit
         */
        private function prepareQuery( array $users, $limit ) {
-               global $wgActorTableSchemaMigrationStage;
-
                $this->resetQueryParams();
                $db = $this->getDB();
 
                $revQuery = MediaWikiServices::getInstance()->getRevisionStore()->getQueryInfo( [ 'page' ] );
 
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       $revWhere = ActorMigration::newMigration()->getWhere( $db, 'rev_user', $users );
-                       $orderUserField = 'rev_actor';
-                       $userField = $this->orderBy === 'actor' ? 'revactor_actor' : 'actor_name';
-                       $tsField = 'revactor_timestamp';
-                       $idField = 'revactor_rev';
-
-                       // T221511: MySQL/MariaDB (10.1.37) can sometimes irrationally decide that querying `actor`
-                       // before `revision_actor_temp` and filesorting is somehow better than querying $limit+1 rows
-                       // from `revision_actor_temp`. Tell it not to reorder the query (and also reorder it ourselves
-                       // because as generated by RevisionStore it'll have `revision` first rather than
-                       // `revision_actor_temp`). But not when uctag is used, as it seems as likely to be harmed as
-                       // helped in that case, and not when there's only one User because in that case it fetches
-                       // the one `actor` row as a constant and doesn't filesort.
-                       if ( count( $users ) > 1 && !isset( $this->params['tag'] ) ) {
-                               $revQuery['joins']['revision'] = $revQuery['joins']['temp_rev_user'];
-                               unset( $revQuery['joins']['temp_rev_user'] );
-                               $this->addOption( 'STRAIGHT_JOIN' );
-                               // It isn't actually necesssary to reorder $revQuery['tables'] as Database does the right thing
-                               // when join conditions are given for all joins, but Gergő is wary of relying on that so pull
-                               // `revision_actor_temp` to the start.
-                               $revQuery['tables'] =
-                                       [ 'temp_rev_user' => $revQuery['tables']['temp_rev_user'] ] + $revQuery['tables'];
-                       }
-               } else {
-                       // If we're dealing with user names (rather than IDs) in read-old mode,
-                       // pass false for ActorMigration::getWhere()'s $useId parameter so
-                       // $revWhere['conds'] isn't an OR.
-                       $revWhere = ActorMigration::newMigration()
-                               ->getWhere( $db, 'rev_user', $users, $this->orderBy === 'id' );
-                       $orderUserField = $this->orderBy === 'id' ? 'rev_user' : 'rev_user_text';
-                       $userField = $revQuery['fields'][$orderUserField];
-                       $tsField = 'rev_timestamp';
-                       $idField = 'rev_id';
+               $revWhere = ActorMigration::newMigration()->getWhere( $db, 'rev_user', $users );
+               $orderUserField = 'rev_actor';
+               $userField = $this->orderBy === 'actor' ? 'revactor_actor' : 'actor_name';
+               $tsField = 'revactor_timestamp';
+               $idField = 'revactor_rev';
+
+               // T221511: MySQL/MariaDB (10.1.37) can sometimes irrationally decide that querying `actor`
+               // before `revision_actor_temp` and filesorting is somehow better than querying $limit+1 rows
+               // from `revision_actor_temp`. Tell it not to reorder the query (and also reorder it ourselves
+               // because as generated by RevisionStore it'll have `revision` first rather than
+               // `revision_actor_temp`). But not when uctag is used, as it seems as likely to be harmed as
+               // helped in that case, and not when there's only one User because in that case it fetches
+               // the one `actor` row as a constant and doesn't filesort.
+               if ( count( $users ) > 1 && !isset( $this->params['tag'] ) ) {
+                       $revQuery['joins']['revision'] = $revQuery['joins']['temp_rev_user'];
+                       unset( $revQuery['joins']['temp_rev_user'] );
+                       $this->addOption( 'STRAIGHT_JOIN' );
+                       // It isn't actually necesssary to reorder $revQuery['tables'] as Database does the right thing
+                       // when join conditions are given for all joins, but Gergő is wary of relying on that so pull
+                       // `revision_actor_temp` to the start.
+                       $revQuery['tables'] =
+                               [ 'temp_rev_user' => $revQuery['tables']['temp_rev_user'] ] + $revQuery['tables'];
                }
 
                $this->addTables( $revQuery['tables'] );
index 12d7435..28dea3b 100644 (file)
@@ -303,32 +303,17 @@ class ApiQueryUserInfo extends ApiQueryBase {
         * @return string|null ISO 8601 timestamp of current user's last contribution or null if none
         */
        protected function getLatestContributionTime() {
-               global $wgActorTableSchemaMigrationStage;
-
                $user = $this->getUser();
                $dbr = $this->getDB();
 
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       if ( $user->getActorId() === null ) {
-                               return null;
-                       }
-                       $res = $dbr->selectField( 'revision_actor_temp',
-                               'MAX(revactor_timestamp)',
-                               [ 'revactor_actor' => $user->getActorId() ],
-                               __METHOD__
-                       );
-               } else {
-                       if ( $user->isLoggedIn() ) {
-                               $conds = [ 'rev_user' => $user->getId() ];
-                       } else {
-                               $conds = [ 'rev_user_text' => $user->getName() ];
-                       }
-                       $res = $dbr->selectField( 'revision',
-                               'MAX(rev_timestamp)',
-                               $conds,
-                               __METHOD__
-                       );
+               if ( $user->getActorId() === null ) {
+                       return null;
                }
+               $res = $dbr->selectField( 'revision_actor_temp',
+                       'MAX(revactor_timestamp)',
+                       [ 'revactor_actor' => $user->getActorId() ],
+                       __METHOD__
+               );
 
                return $res ? wfTimestamp( TS_ISO_8601, $res ) : null;
        }
index 7783826..6b1c217 100644 (file)
@@ -21,6 +21,7 @@
  */
 
 use MediaWiki\Auth\AuthManager;
+use MediaWiki\MediaWikiServices;
 
 /**
  * Reset password, with AuthManager
@@ -63,7 +64,11 @@ class ApiResetPassword extends ApiBase {
 
                $this->requireOnlyOneParameter( $params, 'user', 'email' );
 
-               $passwordReset = new PasswordReset( $this->getConfig(), AuthManager::singleton() );
+               $passwordReset = new PasswordReset(
+                       $this->getConfig(),
+                       AuthManager::singleton(),
+                       MediaWikiServices::getInstance()->getPermissionManager()
+               );
 
                $status = $passwordReset->isAllowed( $this->getUser() );
                if ( !$status->isOK() ) {
index 1ee91c2..60b24f0 100644 (file)
@@ -38,12 +38,6 @@ class ApiRevisionDelete extends ApiBase {
                $user = $this->getUser();
                $this->checkUserRightsAny( RevisionDeleter::getRestriction( $params['type'] ) );
 
-               // @TODO Use PermissionManager::isBlockedFrom() instead.
-               $block = $user->getBlock();
-               if ( $block ) {
-                       $this->dieBlocked( $block );
-               }
-
                if ( !$params['ids'] ) {
                        $this->dieWithError( [ 'apierror-paramempty', 'ids' ], 'paramempty_ids' );
                }
@@ -97,6 +91,10 @@ class ApiRevisionDelete extends ApiBase {
                        $this->dieWithError( [ 'apierror-revdel-needtarget' ], 'needtarget' );
                }
 
+               if ( $this->getPermissionManager()->isBlockedFrom( $user, $targetObj ) ) {
+                       $this->dieBlocked( $user->getBlock() );
+               }
+
                $list = RevisionDeleter::createList(
                        $params['type'], $this->getContext(), $targetObj, $params['ids']
                );
index d2bbe7b..3f6f14c 100644 (file)
@@ -93,13 +93,14 @@ class ApiSetNotificationTimestamp extends ApiBase {
                        $titles = $pageSet->getGoodTitles();
                        $title = reset( $titles );
                        if ( $title ) {
-                               $revid = $title->getNextRevisionID( $params['newerthanrevid'], Title::GAID_FOR_UPDATE );
-                               if ( $revid ) {
-                                       $timestamp = $dbw->timestamp(
-                                               MediaWikiServices::getInstance()->getRevisionStore()->getTimestampFromId( $title, $revid )
-                                       );
-                               } else {
-                                       $timestamp = null;
+                               $timestamp = null;
+                               $rl = MediaWikiServices::getInstance()->getRevisionLookup();
+                               $currRev = $rl->getRevisionById( $params['newerthanrevid'], Title::READ_LATEST );
+                               if ( $currRev ) {
+                                       $nextRev = $rl->getNextRevision( $currRev, Title::READ_LATEST );
+                                       if ( $nextRev ) {
+                                               $timestamp = $dbw->timestamp( $nextRev->getTimestamp() );
+                                       }
                                }
                        }
                }
index aff0183..bb6c580 100644 (file)
@@ -20,7 +20,6 @@
  */
 
 use MediaWiki\MediaWikiServices;
-use MediaWiki\Revision\RevisionStore;
 
 /**
  * @ingroup API
@@ -28,7 +27,9 @@ use MediaWiki\Revision\RevisionStore;
  */
 class ApiTag extends ApiBase {
 
-       /** @var RevisionStore */
+       use ApiBlockInfoTrait;
+
+       /** @var \MediaWiki\Revision\RevisionStore */
        private $revisionStore;
 
        public function execute() {
@@ -40,9 +41,9 @@ class ApiTag extends ApiBase {
                // make sure the user is allowed
                $this->checkUserRightsAny( 'changetags' );
 
-               // @TODO Use PermissionManager::isBlockedFrom() instead.
+               // Fail early if the user is sitewide blocked.
                $block = $user->getBlock();
-               if ( $block ) {
+               if ( $block && $block->isSitewide() ) {
                        $this->dieBlocked( $block );
                }
 
@@ -85,6 +86,7 @@ class ApiTag extends ApiBase {
        }
 
        protected function processIndividual( $type, $params, $id ) {
+               $user = $this->getUser();
                $idResult = [ $type => $id ];
 
                // validate the ID
@@ -92,9 +94,30 @@ class ApiTag extends ApiBase {
                switch ( $type ) {
                        case 'rcid':
                                $valid = RecentChange::newFromId( $id );
+                               if ( $valid && $this->getPermissionManager()->isBlockedFrom( $user, $valid->getTitle() ) ) {
+                                       $idResult['status'] = 'error';
+                                       $idResult += $this->getErrorFormatter()->formatMessage( ApiMessage::create(
+                                               'apierror-blocked',
+                                               'blocked',
+                                               [ 'blockinfo' => $this->getBlockDetails( $user->getBlock() ) ]
+                                       ) );
+                                       return $idResult;
+                               }
                                break;
                        case 'revid':
                                $valid = $this->revisionStore->getRevisionById( $id );
+                               if (
+                                       $valid &&
+                                       $this->getPermissionManager()->isBlockedFrom( $user, $valid->getPageAsLinkTarget() )
+                               ) {
+                                       $idResult['status'] = 'error';
+                                       $idResult += $this->getErrorFormatter()->formatMessage( ApiMessage::create(
+                                                       'apierror-blocked',
+                                                       'blocked',
+                                                       [ 'blockinfo' => $this->getBlockDetails( $user->getBlock() ) ]
+                                       ) );
+                                       return $idResult;
+                               }
                                break;
                        case 'logid':
                                $valid = self::validateLogId( $id );
index dc9c516..58d2dee 100644 (file)
        "apierror-cantoverwrite-sharedfile": "الملف الهدف موجود في مستودع مشترك وليست لديك صلاحية لتجاوزه.",
        "apierror-cantsend": "لم تقم بتسجيل الدخول أو ليس لديك عنوان بريد إلكتروني مؤكد أو غير مسموح لك بإرسال بريد إلكتروني إلى مستخدمين آخرين; لذلك لا يمكنك إرسال بريد إلكتروني.",
        "apierror-cantundelete": "تعذر الاسترجاع: قد لا تكون المراجعات المطلوبة موجودة، أو ربما تم الاسترجاع بالفعل.",
+       "apierror-cantview-deleted-comment": "ليست لديك صلاحية لعرض التعليقات المحذوفة.",
+       "apierror-cantview-deleted-description": "ليست لديك صلاحية لعرض أوصاف الملفات المحذوفة.",
+       "apierror-cantview-deleted-metadata": "ليست لديك صلاحية لعرض البيانات الوصفية للملفات المحذوفة.",
+       "apierror-cantview-deleted-revision-content": "ليست لديك صلاحية لعرض محتوى المراجعات المحذوفة.",
        "apierror-changeauth-norequest": "فشل في إنشاء طلب التغيير.",
        "apierror-chunk-too-small": "الحد الأدنى لحجم القطعة هو $1 {{PLURAL:$1|بايت}} للقطع غير النهائية.",
        "apierror-cidrtoobroad": "لا يُقبَل مدى $1 CIDR أكبر من /$2.",
index 8b42a07..cc5e872 100644 (file)
        "apierror-cantoverwrite-sharedfile": "The target file exists on a shared repository and you do not have permission to override it.",
        "apierror-cantsend": "You are not logged in, you do not have a confirmed email address, or you are not allowed to send email to other users, so you cannot send email.",
        "apierror-cantundelete": "Couldn't undelete: the requested revisions may not exist, or may have been undeleted already.",
+       "apierror-cantview-deleted-comment": "You don't have permission to view deleted comments.",
+       "apierror-cantview-deleted-description": "You don't have permission to view descriptions of deleted files.",
+       "apierror-cantview-deleted-metadata": "You don't have permission to view metadata of deleted files.",
+       "apierror-cantview-deleted-revision-content": "You don't have permission to view content of deleted revisions.",
        "apierror-changeauth-norequest": "Failed to create change request.",
        "apierror-chunk-too-small": "Minimum chunk size is $1 {{PLURAL:$1|byte|bytes}} for non-final chunks.",
        "apierror-cidrtoobroad": "$1 CIDR ranges broader than /$2 are not accepted.",
index b72d519..5ce00f5 100644 (file)
                        "Lucas Werkmeister (WMDE)"
                ]
        },
-       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> L’API MediaWiki est une interface stable et mature qui est supportée et améliorée de façon active. Bien que nous essayions de l’éviter, nous pouvons avoir parfois besoin de faire des modifications impactantes ; inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion mediawiki-api-announce] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> Si des requêtes erronées sont envoyées à l’API, un entête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet entête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Errors and warnings]].\n\n<p class=\"mw-apisandbox-link\"><strong>Test :</strong> Pour faciliter le test des requêtes à l’API, voyez [[Special:ApiSandbox]].</p>",
+       "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Documentation]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Liste de diffusion]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Annonces de l’API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Bogues et demandes]\n</div>\n<strong>État :</strong> l’API de MediaWiki est une interface stable et mature qui est supportée et améliorée de façon active. Bien que nous essayions de l’éviter, nous pouvons avoir parfois besoin de faire des modifications impactantes ; inscrivez-vous à [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ la liste de diffusion ''mediawiki-api-announce''] pour être informé des mises à jour.\n\n<strong>Requêtes erronées :</strong> si des requêtes erronées sont envoyées à l’API, un entête HTTP sera renvoyé avec la clé « MediaWiki-API-Error ». La valeur de cet entête et le code d’erreur renvoyé prendront la même valeur. Pour plus d’information, voyez [[mw:Special:MyLanguage/API:Errors_and_warnings|API:Errors and warnings]].\n\n<p class=\"mw-apisandbox-link\"><strong>Test :</strong> Pour faciliter le test des requêtes à l’API, voyez [[Special:ApiSandbox]].</p>",
        "apihelp-main-param-action": "Quelle action effectuer.",
        "apihelp-main-param-format": "Le format de sortie.",
-       "apihelp-main-param-maxlag": "La latence maximale peut être utilisée quand MédiaWiki est installé sur un cluster de base de données répliqué. Pour éviter des actions provoquant un supplément de latence de réplication de site, ce paramètre peut faire attendre le client jusqu’à ce que la latence de réplication soit inférieure à une valeur spécifiée. En cas de latence excessive, le code d’erreur <samp>maxlag</samp> est renvoyé avec un message tel que <samp>Attente de $host : $lag secondes de délai</samp>.<br />Voyez [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manuel: paramètre Maxlag]] pour plus d’information.",
+       "apihelp-main-param-maxlag": "La latence maximale peut être utilisée quand MediaWiki est installé sur une grappe de réplication de base de données. Pour éviter des actions provoquant un supplément de latence de réplication de site, ce paramètre peut faire attendre le client jusqu’à ce que la latence de réplication soit inférieure à une valeur spécifiée. En cas de latence excessive, le code d’erreur <samp>maxlag</samp> est renvoyé avec un message tel que <samp>Attente de $host : $lag secondes de délai</samp>.<br />Voyez [[mw:Special:MyLanguage/Manual:Maxlag_parameter|Manuel : paramètre Maxlag]] pour plus d’informations.",
        "apihelp-main-param-smaxage": "Fixer l’entête HTTP de contrôle de cache <code>s-maxage</code> à ce nombre de secondes. Les erreurs ne sont jamais mises en cache.",
        "apihelp-main-param-maxage": "Fixer l’entête HTTP de contrôle de cache <code>max-age</code> à ce nombre de secondes. Les erreurs ne sont jamais mises en cache.",
-       "apihelp-main-param-assert": "Vérifier si l’utilisateur est connecté si la valeur est <kbd>user</kbd>, ou s’il a le droit d’un utilisateur robot si la valeur est <kbd>bot</kbd>.",
+       "apihelp-main-param-assert": "Vérifier que l’utilisateur est connecté lorsque la valeur est <kbd>user</kbd> ou qu’il a le droit d’un utilisateur robot lorsque la valeur est <kbd>bot</kbd>.",
        "apihelp-main-param-assertuser": "Vérifier que l’utilisateur actuel est l’utilisateur nommé.",
        "apihelp-main-param-requestid": "Toute valeur fournie ici sera incluse dans la réponse. Peut être utilisé pour distinguer des demandes.",
        "apihelp-main-param-servedby": "Inclure le nom d’hôte qui a renvoyé la requête dans les résultats.",
@@ -51,7 +51,7 @@
        "apihelp-main-param-responselanginfo": "Inclure les langues utilisées pour <var>uselang</var> et <var>errorlang</var> dans le résultat.",
        "apihelp-main-param-origin": "En accédant à l’API en utilisant une requête AJAX inter-domaines (CORS), mettre le domaine d’origine dans ce paramètre. Il doit être inclus dans toute requête de pre-flight, et doit donc faire partie de l’URI de la requête (pas du corps du POST).\n\nPour les requêtes authentifiées, il doit correspondre exactement à une des origines dans l’entête <code>Origin</code> header, donc il doit être fixé avec quelque chose comme <kbd>https://en.wikipedia.org</kbd> ou <kbd>https://meta.wikimedia.org</kbd>. Si ce paramètre ne correspond pas à l’entête <code>Origin</code>, une réponse 403 sera renvoyée. Si ce paramètre correspond à l’entête <code>Origin</code> et que l’origine est en liste blanche, des entêtes <code>Access-Control-Allow-Origin</code> et <code>Access-Control-Allow-Credentials</code> seront positionnés.\n\nPour les requêtes non authentifiées, spécifiez la valeur <kbd>*</kbd>. Cela positionnera l’entête <code>Access-Control-Allow-Origin</code>, mais <code>Access-Control-Allow-Credentials</code> vaudra <code>false</code> et toutes les données spécifiques à l’utilisateur seront filtrées.",
        "apihelp-main-param-uselang": "Langue à utiliser pour les traductions de message. <kbd>[[Special:ApiHelp/query+siteinfo|action=query&meta=siteinfo]]</kbd> avec <kbd>siprop=languages</kbd> renvoie une liste de codes de langue, ou en spécifiant <kbd>user</kbd> pour utiliser la préférence de langue de l’utilisateur actuel, ou en spécifiant <kbd>content</kbd> pour utiliser le langage du contenu de ce wiki.",
-       "apihelp-main-param-errorformat": "Format à utiliser pour la sortie du texte d’avertissement et d’erreur.\n; plaintext: Wikitexte avec balises HTML supprimées et les entités remplacées.\n; wikitext: wikitexte non analysé.\n; html: HTML.\n; raw: Clé de message et paramètres.\n; none: Aucune sortie de texte, uniquement les codes erreur.\n; bc: Format utilisé avant MédiaWiki 1.29. <var>errorlang</var> et <var>errorsuselocal</var> sont ignorés.",
+       "apihelp-main-param-errorformat": "Format à utiliser pour la sortie du texte d’avertissement et d’erreur.\n; plaintext: Wikitexte avec balises HTML supprimées et les entités remplacées.\n; wikitext: wikitexte non analysé.\n; html: HTML.\n; raw: Clé de message et paramètres.\n; none: Aucune sortie de texte, uniquement les codes erreur.\n; bc: Format utilisé avant MediaWiki 1.29. <var>errorlang</var> et <var>errorsuselocal</var> sont ignorés.",
        "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-summary": "Bloquer un utilisateur.",
@@ -86,7 +86,7 @@
        "apihelp-clientlogin-example-login": "Commencer le processus de connexion au wiki en tant qu’utilisateur <kbd>Exemple</kbd> avec le mot de passe <kbd>ExempleMotDePasse</kbd>.",
        "apihelp-clientlogin-example-login2": "Continuer la connexion après une réponse de l’<samp>IHM</samp> pour l’authentification à deux facteurs, en fournissant un <var>OATHToken</var> valant <kbd>987654</kbd>.",
        "apihelp-compare-summary": "Obtenir la différence entre deux pages.",
-       "apihelp-compare-extended-description": "Vous devez passer un numéro de révision, un titre de page, ou un ID de page, à la fois pour « from » et « to ».",
+       "apihelp-compare-extended-description": "Vous devez passer un numéro de révision, un titre de page, ou un ID de page, à la fois pour « from » et « to ».",
        "apihelp-compare-param-fromtitle": "Premier titre à comparer.",
        "apihelp-compare-param-fromid": "ID de la première page à comparer.",
        "apihelp-compare-param-fromrev": "Première révision à comparer.",
        "apihelp-edit-param-summary": "Modifier le résumé. Également le titre de la section quand $1section=new et $1sectiontitle n’est pas défini.",
        "apihelp-edit-param-tags": "Modifier les balises à appliquer à la version.",
        "apihelp-edit-param-minor": "Marquer cette modification comme étant mineure.",
-       "apihelp-edit-param-notminor": "Ne pas marquer cette modification comme mineure, même si la préférence utilisateur « {{int:tog-minordefault}} » est positionnée.",
+       "apihelp-edit-param-notminor": "Ne pas marquer cette modification comme mineure, même si la préférence utilisateur « {{int:tog-minordefault}} » est positionnée.",
        "apihelp-edit-param-bot": "Marquer cette modification comme effectuée par un robot.",
        "apihelp-edit-param-basetimestamp": "Horodatage de la révision de base, utilisé pour détecter les conflits de modification. Peut être obtenu via [[Special:ApiHelp/query+revisions|action=query&prop=revisions&rvprop=timestamp]].",
        "apihelp-edit-param-starttimestamp": "L'horodatage, lorsque le processus d'édition est démarré, est utilisé pour détecter les conflits de modification. Une valeur appropriée peut être obtenue en utilisant <var>[[Special:ApiHelp/main|curtimestamp]]</var> lors du démarrage du processus d'édition (par ex. en chargeant le contenu de la page à modifier).",
        "apihelp-opensearch-param-limit": "Nombre maximal de résultats à renvoyer.",
        "apihelp-opensearch-param-namespace": "Espaces de nom à rechercher.  Ignoré if <var>$1search</var> commence avec le préfixe d'un espace de noms valide.",
        "apihelp-opensearch-param-suggest": "Ne rien faire si <var>[[mw:Special:MyLanguage/Manual:$wgEnableOpenSearchSuggest|$wgEnableOpenSearchSuggest]]</var> vaut faux.",
-       "apihelp-opensearch-param-redirects": "Comment gérer les redirections :\n;return:Renvoie la redirection elle-même.\n;resolve:Renvoie la page cible. Peut renvoyer moins de $1limit résultats.\nPour des raisons historiques, la valeur par défaut est « return » pour $1format=json et « resolve » pour les autres formats.",
+       "apihelp-opensearch-param-redirects": "Comment gérer les redirections :\n;return:Renvoie la redirection elle-même.\n;resolve:Renvoie la page cible. Peut renvoyer moins de $1limit résultats.\nPour des raisons historiques, la valeur par défaut est « return » pour $1format=json et « resolve » pour les autres formats.",
        "apihelp-opensearch-param-format": "Le format de sortie.",
        "apihelp-opensearch-param-warningsaserror": "Si des avertissements apparaissent avec <kbd>format=json</kbd>, renvoyer une erreur d’API au lieu de les ignorer.",
        "apihelp-opensearch-example-te": "Trouver les pages commençant par <kbd>Te</kbd>.",
        "apihelp-parse-param-effectivelanglinks": "Inclut les liens de langue fournis par les extensions (à utiliser avec <kbd>$1prop=langlinks</kbd>).",
        "apihelp-parse-param-section": "Traiter uniquement le contenu de la section ayant ce numéro.\n\nQuand la valeur est <kbd>new</kbd>, traite <var>$1text</var> et <var>$1sectiontitle</var> comme s’ils correspondaient à une nouvelle section de la page.\n\nLa valeur <kbd>new</kbd> n’est autorisée que si <var>text</var> est défini.",
        "apihelp-parse-param-sectiontitle": "Nouveau titre de section quand <var>section</var> vaut <kbd>nouveau</kbd>.\n\nÀ la différence de la modification de page, cela ne revient pas à <var>summary</var> quand il est omis ou vide.",
-       "apihelp-parse-param-disablelimitreport": "Omettre le rapport de limite (« rapport de limite du nouveau PP ») de la sortie de l’analyseur.",
+       "apihelp-parse-param-disablelimitreport": "Omettre le rapport de limite (« rapport de limite du nouveau PP ») de la sortie de l’analyseur.",
        "apihelp-parse-param-disablepp": "Utiliser <var>$1disablelimitreport</var> à la place.",
        "apihelp-parse-param-disableeditsection": "Omettre les liens de modification de section de la sortie de l’analyseur.",
        "apihelp-parse-param-disabletidy": "Ne pas exécuter de nettoyage du code HTML (par exemple,  réagencer) sur la sortie de l'analyseur.",
        "apihelp-query+embeddedin-param-limit": "Combien de pages renvoyer au total.",
        "apihelp-query+embeddedin-example-simple": "Afficher les pages incluant <kbd>Template:Stub</kbd>.",
        "apihelp-query+embeddedin-example-generator": "Obtenir des informations sur les pages incluant <kbd>Template:Stub</kbd>.",
-       "apihelp-query+extlinks-summary": "Renvoyer toutes les URLs externes (non interwikis) des pages données.",
+       "apihelp-query+extlinks-summary": "Renvoyer toutes les URL externes (non interwikis) des pages données.",
        "apihelp-query+extlinks-param-limit": "Combien de liens renvoyer.",
        "apihelp-query+extlinks-param-protocol": "Protocole de l’URL. Si vide et <var>$1query</var> est positionné, le protocole est <kbd>http</kbd>. Laisser à la fois ceci et <var>$1query</var> vides pour lister tous les liens externes.",
        "apihelp-query+extlinks-param-query": "Rechercher une chaîne sans protocole. Utile pour vérifier si une certaine page contient une certaine URL externe.",
-       "apihelp-query+extlinks-param-expandurl": "Étendre les URLs relatives au protocole avec le protocole canonique.",
+       "apihelp-query+extlinks-param-expandurl": "Étendre les URL relatives au protocole avec le protocole canonique.",
        "apihelp-query+extlinks-example-simple": "Obtenir une liste des liens externes de <kbd>Main Page</kbd>.",
        "apihelp-query+exturlusage-summary": "Énumérer les pages contenant une URL donnée.",
        "apihelp-query+exturlusage-param-prop": "Quelles informations inclure :",
        "apihelp-query+exturlusage-param-query": "Rechercher une chaîne sans protocole. Voyez [[Special:LinkSearch]]. Le laisser vide pour lister tous les liens externes.",
        "apihelp-query+exturlusage-param-namespace": "Les espaces de nom à énumérer.",
        "apihelp-query+exturlusage-param-limit": "Combien de pages renvoyer.",
-       "apihelp-query+exturlusage-param-expandurl": "Étendre les URLs relatives au protocole avec le protocole canonique.",
+       "apihelp-query+exturlusage-param-expandurl": "Étendre les URL relatives au protocole avec le protocole canonique.",
        "apihelp-query+exturlusage-example-simple": "Afficher les pages avec un lien vers <kbd>https://www.mediawiki.org</kbd>.",
        "apihelp-query+filearchive-summary": "Énumérer séquentiellement tous les fichiers supprimés.",
        "apihelp-query+filearchive-param-from": "Le titre de l’image auquel démarrer l’énumération.",
        "apihelp-query+filearchive-param-limit": "Combien d’images renvoyer au total.",
        "apihelp-query+filearchive-param-dir": "La direction dans laquelle lister.",
        "apihelp-query+filearchive-param-sha1": "Hachage SHA1 de l’image. Écrase $1sha1base36.",
-       "apihelp-query+filearchive-param-sha1base36": "Hachage SHA1 de l’image en base 36 (utilisé dans MédiaWiki).",
+       "apihelp-query+filearchive-param-sha1base36": "Hachage SHA1 de l’image en base 36 (utilisé dans MediaWiki).",
        "apihelp-query+filearchive-param-prop": "Quelle information obtenir sur l’image :",
        "apihelp-query+filearchive-paramvalue-prop-sha1": "Ajoute le hachage SHA-1 pour l’image.",
        "apihelp-query+filearchive-paramvalue-prop-timestamp": "Ajoute l’horodatage à la version téléversée.",
        "apihelp-query+filerepoinfo-paramvalue-prop-local": "Si ce dépôt est local ou non.",
        "apihelp-query+filerepoinfo-paramvalue-prop-name": "La clé du dépôt — utilisée dans les valeurs de retour, par ex. <var>[[mw:Special:MyLanguage/Manual:$wgForeignFileRepos|$wgForeignFileRepos]]</var> et [[Special:ApiHelp/query+imageinfo|imageinfo]] return values.",
        "apihelp-query+filerepoinfo-paramvalue-prop-rootUrl": "Chemin de l’URL racine pour les chemins d’image.",
-       "apihelp-query+filerepoinfo-paramvalue-prop-scriptDirUrl": "Chemin de l’URL racine pour l’installation de MédiaWiki du wiki du dépôt.",
+       "apihelp-query+filerepoinfo-paramvalue-prop-scriptDirUrl": "Chemin de l’URL racine pour l’installation de MediaWiki du wiki du dépôt.",
        "apihelp-query+filerepoinfo-paramvalue-prop-server": "<var>[[mw:Special:MyLanguage/Manual:$wgServer|$wgServer]]</var> du wiki du dépôt, ou équivalent.",
        "apihelp-query+filerepoinfo-paramvalue-prop-thumbUrl": "Chemin de l’URL racine pour les chemins des vignettes.",
        "apihelp-query+filerepoinfo-paramvalue-prop-url": "Chemin de l’URL de la zone publique.",
        "apihelp-query+imageinfo-paramvalue-prop-extmetadata": "Liste les métadonnées mises en forme combinées depuis diverses sources. Les résultats sont au format HTML.",
        "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-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 MediaWiki.",
        "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évisions de fichier renvoyer par fichier.",
        "apihelp-query+imageinfo-param-start": "Horodatage auquel démarrer la liste.",
        "apihelp-query+info-example-simple": "Obtenir des informations sur la page <kbd>Main Page</kbd>.",
        "apihelp-query+info-example-protection": "Obtenir des informations générales et de protection sur la page <kbd>Main Page</kbd>.",
        "apihelp-query+iwbacklinks-summary": "Trouver toutes les pages qui ont un lien vers le lien interwiki indiqué.",
-       "apihelp-query+iwbacklinks-extended-description": "Peut être utilisé pour trouver tous les liens avec un préfixe, ou tous les liens vers un titre (avec un préfixe donné). Sans paramètre, équivaut à « tous les liens interwiki ».",
+       "apihelp-query+iwbacklinks-extended-description": "Peut être utilisé pour trouver tous les liens avec un préfixe, ou tous les liens vers un titre (avec un préfixe donné). Sans paramètre, équivaut à « tous les liens interwiki ».",
        "apihelp-query+iwbacklinks-param-prefix": "Préfixe pour l’interwiki.",
        "apihelp-query+iwbacklinks-param-title": "Lien interwiki à rechercher. Doit être utilisé avec <var>$1blprefix</var>.",
        "apihelp-query+iwbacklinks-param-limit": "Combien de pages renvoyer.",
        "apihelp-query+iwlinks-param-dir": "La direction dans laquelle lister.",
        "apihelp-query+iwlinks-example-simple": "Obtenir les liens interwiki de la page <kbd>Main Page</kbd>.",
        "apihelp-query+langbacklinks-summary": "Trouver toutes les pages qui ont un lien vers le lien de langue indiqué.",
-       "apihelp-query+langbacklinks-extended-description": "Peut être utilisé pour trouver tous les liens avec un code de langue, ou tous les liens vers un titre (avec une langue donnée). Sans paramètre équivaut à « tous les liens de langue ».\n\nNotez que cela peut ne pas prendre en compte les liens de langue ajoutés par les extensions.",
+       "apihelp-query+langbacklinks-extended-description": "Peut être utilisé pour trouver tous les liens avec un code de langue, ou tous les liens vers un titre (avec une langue donnée). Sans paramètre équivaut à « tous les liens de langue ».\n\nNotez que cela peut ne pas prendre en compte les liens de langue ajoutés par les extensions.",
        "apihelp-query+langbacklinks-param-lang": "Langue pour le lien de langue.",
        "apihelp-query+langbacklinks-param-title": "Lien interlangue à rechercher. Doit être utilisé avec $1lang.",
        "apihelp-query+langbacklinks-param-limit": "Combien de pages renvoyer au total.",
        "apihelp-query+languageinfo-summary": "Renvoyer des informations sur les langues disponibles.",
        "apihelp-query+languageinfo-extended-description": "[[mw:API:Query#Continuing queries|Un prolongement]] peut être appliqué si la récupération de l’information prend trop de temps pour une requête.",
        "apihelp-query+languageinfo-param-prop": "Quelle information obtenir pour chaque langue.",
-       "apihelp-query+languageinfo-paramvalue-prop-code": "Le code de langue (ce code est spécifique à MédiaWiki, bien qu’il y ait des recouvrements avec d’autres standards).",
+       "apihelp-query+languageinfo-paramvalue-prop-code": "Le code de langue (ce code est spécifique à MediaWiki, bien qu’il y ait des recouvrements avec d’autres standards).",
        "apihelp-query+languageinfo-paramvalue-prop-bcp47": "Le code de langue BCP-47.",
        "apihelp-query+languageinfo-paramvalue-prop-dir": "La direction d’écriture de la langue (<code>ltr</code> ou <code>rtl</code>).",
        "apihelp-query+languageinfo-paramvalue-prop-autonym": "L’autonyme d’une langue, c’est-à-dire son nom dans cette langue.",
        "apihelp-query+siteinfo-paramvalue-prop-fileextensions": "Renvoie la liste des extensions de fichiers (types de fichiers) autorisées au téléversement.",
        "apihelp-query+siteinfo-paramvalue-prop-rightsinfo": "Renvoie l’information sur les droits du wiki (sa licence), si elle est disponible.",
        "apihelp-query+siteinfo-paramvalue-prop-restrictions": "Renvoie l’information sur les types de restriction disponibles (protection).",
-       "apihelp-query+siteinfo-paramvalue-prop-languages": "Renvoie une liste des langues que MédiaWiki prend en charge (éventuellement localisée en utilisant <var>$1inlanguagecode</var>).",
+       "apihelp-query+siteinfo-paramvalue-prop-languages": "Renvoie une liste des langues que MediaWiki prend en charge (éventuellement localisée en utilisant <var>$1inlanguagecode</var>).",
        "apihelp-query+siteinfo-paramvalue-prop-languagevariants": "Renvoie une liste de codes de langue pour lesquels [[mw:Special:MyLanguage/LanguageConverter|LanguageConverter]] est activé, et les variantes prises en charge pour chacun.",
        "apihelp-query+siteinfo-paramvalue-prop-skins": "Renvoie une liste de tous les habillages activés (éventuellement localisé en utilisant <var>$1inlanguagecode</var>, sinon dans la langue du contenu).",
        "apihelp-query+siteinfo-paramvalue-prop-extensiontags": "Renvoie une liste des balises d’extension de l’analyseur.",
        "apihelp-query+users-paramvalue-prop-editcount": "Ajoute le compteur de modifications de l’utilisateur.",
        "apihelp-query+users-paramvalue-prop-registration": "Ajoute l’horodatage d’inscription de l’utilisateur.",
        "apihelp-query+users-paramvalue-prop-emailable": "Marque si l’utilisateur peut et veut recevoir des courriels via [[Special:Emailuser]].",
-       "apihelp-query+users-paramvalue-prop-gender": "Marque le sexe de l’utilisateur. Renvoie « male », « female », ou « unknown ».",
+       "apihelp-query+users-paramvalue-prop-gender": "Marque le sexe de l’utilisateur. Renvoie « male », « female », ou « unknown ».",
        "apihelp-query+users-paramvalue-prop-centralids": "Ajoute les IDs centraux et l’état d’attachement de l’utilisateur.",
        "apihelp-query+users-paramvalue-prop-cancreate": "Indique si un compte peut être créé pour les noms d’utilisateurs valides mais non enregistrés.",
        "apihelp-query+users-param-attachedwiki": "Avec <kbd>$1prop=centralids</kbd>, indiquer si l’utilisateur est attaché au wiki identifié par cet ID.",
        "apihelp-rsd-summary": "Exporter un schéma RSD (Découverte Très Simple).",
        "apihelp-rsd-example-simple": "Exporter le schéma RSD",
        "apihelp-setnotificationtimestamp-summary": "Mettre à jour l’horodatage de notification pour les pages suivies.",
-       "apihelp-setnotificationtimestamp-extended-description": "Cela affecte la mise en évidence des pages modifiées dans la liste de suivi et l’historique, et l’envoi de courriel quand la préférence « {{int:tog-enotifwatchlistpages}} » est activée.",
+       "apihelp-setnotificationtimestamp-extended-description": "Cela affecte la mise en évidence des pages modifiées dans la liste de suivi et l’historique, et l’envoi de courriel quand la préférence « {{int:tog-enotifwatchlistpages}} » est activée.",
        "apihelp-setnotificationtimestamp-param-entirewatchlist": "Travailler sur toutes les pages suivies.",
        "apihelp-setnotificationtimestamp-param-timestamp": "Horodatage auquel dater la notification.",
        "apihelp-setnotificationtimestamp-param-torevid": "Révision pour laquelle fixer l’horodatage de notification (une page uniquement).",
        "apihelp-unlinkaccount-summary": "Supprimer un compte tiers lié de l’utilisateur actuel.",
        "apihelp-unlinkaccount-example-simple": "Essayer de supprimer le lien de l’utilisateur actuel pour le fournisseur associé avec <kbd>FooAuthenticationRequest</kbd>.",
        "apihelp-upload-summary": "Téléverser un fichier, ou obtenir l’état des téléversements en cours.",
-       "apihelp-upload-extended-description": "Plusieurs méthodes sont disponibles :\n* Téléverser directement le contenu du fichier, en utilisant le paramètre <var>$1file</var>.\n* Téléverser le fichier par morceaux, en utilisant les paramètres <var>$1filesize</var>, <var>$1chunk</var>, and <var>$1offset</var>.\n* Pour que le serveur MédiaWiki cherche un fichier depuis une URL, utilisez le paramètre <var>$1url</var>.\n* Terminer un téléversement précédent qui a échoué à cause d’avertissements, en utilisant le paramètre <var>$1filekey</var>.\nNoter que le POST HTTP doit être fait comme un téléversement de fichier (par exemple en utilisant <code>multipart/form-data</code>) en envoyant le <var>$1file</var>.",
+       "apihelp-upload-extended-description": "Plusieurs méthodes sont disponibles :\n* Téléverser directement le contenu du fichier, en utilisant le paramètre <var>$1file</var>.\n* Téléverser le fichier par morceaux, en utilisant les paramètres <var>$1filesize</var>, <var>$1chunk</var>, and <var>$1offset</var>.\n* Pour que le serveur MediaWiki cherche un fichier depuis une URL, utilisez le paramètre <var>$1url</var>.\n* Terminer un téléversement précédent qui a échoué à cause d’avertissements, en utilisant le paramètre <var>$1filekey</var>.\nNoter que le POST HTTP doit être fait comme un téléversement de fichier (par exemple en utilisant <code>multipart/form-data</code>) en envoyant le <var>$1file</var>.",
        "apihelp-upload-param-filename": "Nom de fichier cible.",
        "apihelp-upload-param-comment": "Téléverser le commentaire. Utilisé aussi comme texte de la page initiale pour les nouveaux fichiers si <var>$1text</var> n’est pas spécifié.",
        "apihelp-upload-param-tags": "Modifier les balises à appliquer à l’entrée du journal de téléversement et à la révision de la page du fichier.",
        "api-pageset-param-titles": "Une liste des titres sur lesquels travailler.",
        "api-pageset-param-pageids": "Une liste des IDs de pages sur lesquelles travailler.",
        "api-pageset-param-revids": "Une liste des IDs de révisions sur lesquelles travailler.",
-       "api-pageset-param-generator": "Obtenir la liste des pages sur lesquelles travailler en exécutant le module de requête spécifié.\n\n<strong>NOTE :<strong> les noms de paramètre du générateur doivent être préfixés avec un « g », voir les exemples.",
+       "api-pageset-param-generator": "Obtenir la liste des pages sur lesquelles travailler en exécutant le module de requête spécifié.\n\n<strong>NOTE :<strong> les noms de paramètre du générateur doivent être préfixés avec un « g », voir les exemples.",
        "api-pageset-param-redirects-generator": "Résoudre automatiquement les redirections dans <var>$1titles</var>, <var>$1pageids</var> et <var>$1revids</var>, et dans les pages renvoyées par <var>$1generator</var>.",
        "api-pageset-param-redirects-nogenerator": "Résoudre automatiquement les redirections dans <var>$1titles</var>, <var>$1pageids</var> et <var>$1revids</var>.",
        "api-pageset-param-converttitles": "Convertir les titres dans d’autres variantes si nécessaire. Fonctionne uniquement si la langue de contenu du wiki prend en charge la conversion en variantes. Les langues qui prennent en charge la conversion en variantes incluent $1.",
        "api-help-param-templated-var-first": "<var>&#x7B;$1&#x7D;</var> dans le nom du paramètre doit être remplacé par des valeurs de <var>$2</var>",
        "api-help-param-templated-var": "<var>&#x7B;$1&#x7D;</var> par les valeurs de <var>$2</var>",
        "api-help-datatypes-header": "Type de données",
-       "api-help-datatypes": "Les entrées dans MédiaWiki doivent être en UTF-8 à la norme NFC. MédiaWiki peut tenter de convertir d’autres types d’entrées, mais cela peut faire échouer certaines opérations (comme les [[Special:ApiHelp/edit|modifications]] avec contrôles MD5).\n\nCertains types de paramètres dans les requêtes de l’API nécessitent plus d’explication&nbsp;:\n;boolean\n:Les paramètres booléens fonctionnent comme des cases à cocher HTML&nbsp;: si le paramètre est spécifié, quelle que soit sa valeur, il est considéré comme vrai. Pour une valeur fausse, enlever complètement le paramètre.\n;timestamp\n:Les horodatages peuvent être spécifiés sous différentes formes, voir [[mw:Special:MyLanguage/Timestamp|les formats d’entrées de la librairie Timestampdocumentés sur mediawiki.org]] pour plus de détails. La date et heure ISO 8601 est recommandée&nbsp;: <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd>. De plus, la chaîne de caractères <kbd>now</kbd> peut être utilisée pour spécifier le fuseau horaire actuel.\n;séparateur multi-valeurs alternatif\n:Les paramètres prenant plusieurs valeurs sont normalement validés lorsque celles-ci sont séparées par le caractère «&nbsp;pipe&nbsp;» (|), ex. <kbd>paramètre=valeur1|valeur2</kbd> ou <kbd>paramètre=valeur1%7Cvaleur2</kbd>. Si une valeur doit contenir le caractère «&nbsp;pipe&nbsp;», utiliser U+001F (séparateur de sous-articles) comme séparateur ''et'' la préfixer de U+001F, ex. <kbd>paramètre=%1Fvaleur1%1Fvaleur2</kbd>.",
+       "api-help-datatypes": "Les entrées dans MediaWiki doivent être en UTF-8 à la norme NFC. MediaWiki peut tenter de convertir d’autres types d’entrées, mais cela peut faire échouer certaines opérations (comme les [[Special:ApiHelp/edit|modifications]] avec contrôles MD5).\n\nCertains types de paramètres dans les requêtes de l’API nécessitent plus d’explication&nbsp;:\n;boolean\n:Les paramètres booléens fonctionnent comme des cases à cocher HTML&nbsp;: si le paramètre est spécifié, quelle que soit sa valeur, il est considéré comme vrai. Pour une valeur fausse, enlever complètement le paramètre.\n;timestamp\n:Les horodatages peuvent être spécifiés sous différentes formes, voir [[mw:Special:MyLanguage/Timestamp|les formats d’entrées de la librairie Timestampdocumentés sur mediawiki.org]] pour plus de détails. La date et heure ISO 8601 est recommandée&nbsp;: <kbd><var>2001</var>-<var>01</var>-<var>15</var>T<var>14</var>:<var>56</var>:<var>00</var>Z</kbd>. De plus, la chaîne de caractères <kbd>now</kbd> peut être utilisée pour spécifier le fuseau horaire actuel.\n;séparateur multi-valeurs alternatif\n:Les paramètres prenant plusieurs valeurs sont normalement validés lorsque celles-ci sont séparées par le caractère «&nbsp;pipe&nbsp;» (|), ex. <kbd>paramètre=valeur1|valeur2</kbd> ou <kbd>paramètre=valeur1%7Cvaleur2</kbd>. Si une valeur doit contenir le caractère «&nbsp;pipe&nbsp;», utiliser U+001F (séparateur de sous-articles) comme séparateur ''et'' la préfixer de U+001F, ex. <kbd>paramètre=%1Fvaleur1%1Fvaleur2</kbd>.",
        "api-help-templatedparams-header": "Paramètres de modèle",
        "api-help-templatedparams": "Les paramètres de modèle supportent les cas où un module d’API a besoin d’une valeur pour chaque valeur d’un autre paramètre quelconque. Par exemple, s’il y avait un module d’API pour demander un fruit, il pourrait avoir un paramètre <var>fruits</var> pour spécifier quels fruits sont demandés et un paramètre de modèle <var>{fruit}-quantité</var> pour spécifier la quantité demandée de chaque fruit. Un client de l’API qui voudrait une pomme, cinq bananes et vingt fraises pourrait alors faire une requête comme <kbd>fruits=pommes|bananes|fraises&pommes-quantité=1&bananes-quantité=5&fraises-quantité=20</kbd>.",
        "api-help-param-type-limit": "Type : entier ou <kbd>max</kbd>",
        "api-help-param-multi-all": "Pour spécifier toutes les valeurs, utiliser <kbd>$1</kbd>.",
        "api-help-param-default": "Par défaut : $1",
        "api-help-param-default-empty": "Par défaut : <span class=\"apihelp-empty\">(vide)</span>",
-       "api-help-param-token": "Un jeton « $1 » récupéré par [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
+       "api-help-param-token": "Un jeton « $1 » récupéré par [[Special:ApiHelp/query+tokens|action=query&meta=tokens]]",
        "api-help-param-token-webui": "Pour rester compatible, le jeton utilisé dans l’IHM web est aussi accepté.",
        "api-help-param-disabled-in-miser-mode": "Désactivé à cause du [[mw:Special:MyLanguage/Manual:$wgMiserMode|mode minimal]].",
        "api-help-param-limited-in-miser-mode": "<strong>NOTE :</strong> Du fait du [[mw:Special:MyLanguage/Manual:$wgMiserMode|mode minimal]], utiliser cela peut aboutir à moins de résultats que <var>$1limit</var> renvoyés avant de continuer ; dans les cas extrêmes, zéro résultat peut être renvoyé.",
        "apierror-appendnotsupported": "Impossible d’ajouter aux pages utilisant le modèle de contenu $1.",
        "apierror-articleexists": "L’article que vous essayez de créer l’a déjà été.",
        "apierror-assertbotfailed": "La vérification que l’utilisateur a le droit <code>bot</code> a échoué.",
-       "apierror-assertnameduserfailed": "La vérification que l’utilisateur est « $1 » a échoué.",
+       "apierror-assertnameduserfailed": "La vérification que l’utilisateur est « $1 » a échoué.",
        "apierror-assertuserfailed": "La vérification que l’utilisateur est connecté a échoué.",
        "apierror-autoblocked": "Votre adresse IP a été bloquée automatiquement, parce qu’elle a été utilisée par un utilisateur bloqué.",
        "apierror-bad-badfilecontexttitle": "Titre invalide dans le paramètre <var>$1badfilecontexttitle</var> .",
        "apierror-badgenerator-unknown": "<kbd>generator=$1</kbd> inconnu.",
        "apierror-badip": "Paramètre IP non valide.",
        "apierror-badmd5": "Le hachage MD5 fourni n’était pas correct.",
-       "apierror-badmodule-badsubmodule": "Le module <kbd>$1</kbd> n’a pas de sous-module « $2 ».",
+       "apierror-badmodule-badsubmodule": "Le module <kbd>$1</kbd> n’a pas de sous-module « $2 ».",
        "apierror-badmodule-nosubmodules": "Le module <kbd>$1</kbd> n’a pas de sous-modules.",
        "apierror-badparameter": "Valeur non valide pour le paramètre <var>$1</var>.",
        "apierror-badquery": "Requête invalide.",
-       "apierror-badtimestamp": "Valeur non valide « $2 » pour le paramètre de référence horaire  <var>$1</var>.",
+       "apierror-badtimestamp": "Valeur non valide « $2 » pour le paramètre de référence horaire  <var>$1</var>.",
        "apierror-badtoken": "Jeton CSRF non valide.",
        "apierror-badupload": "Le paramètre de téléversement de fichier <var>$1</var> n’est pas un téléversement de fichier ; assurez-vous d’utiliser <code>multipart/form-data</code> pour votre POST et d’inclure un nom de fichier dans l’entête <code>Content-Disposition</code>.",
-       "apierror-badurl": "Valeur « $2 » non valide pour le paramètre d’URL <var>$1</var>.",
-       "apierror-baduser": "Valeur « $2 » non valide pour le paramètre utilisateur <var>$1</var>.",
+       "apierror-badurl": "Valeur « $2 » non valide pour le paramètre d’URL <var>$1</var>.",
+       "apierror-baduser": "Valeur « $2 » non valide pour le paramètre utilisateur <var>$1</var>.",
        "apierror-badvalue-notmultivalue": "La séparation multi-valeur U+001F ne peut être utilisée que pour des paramètres multi-valeurs.",
        "apierror-bad-watchlist-token": "Jeton de liste de suivi fourni non valide. Veuillez mettre un jeton valide dans [[Special:Preferences]].",
        "apierror-blockedfrommail": "Vous avez été bloqué pour l’envoi de courriel.",
        "apierror-cantoverwrite-sharedfile": "Le fichier cible existe dans un dépôt partagé et vous n’avez pas le droit de l’écraser.",
        "apierror-cantsend": "Vous n’êtes pas connecté, vous n’avez pas d’adresse de courriel confirmée, ou vous n’êtes pas autorisé à envoyer des courriels aux autres utilisateurs, donc vous ne pouvez envoyer de courriel.",
        "apierror-cantundelete": "Impossible d’annuler : les révisions demandées peuvent ne plus exister, ou avoir déjà été annulées.",
+       "apierror-cantview-deleted-comment": "Vous n’avez pas la permission de visualiser les commentaires supprimés.",
+       "apierror-cantview-deleted-description": "Vous n’avez pas le droit d’afficher les descriptions des fichiers supprimés.",
+       "apierror-cantview-deleted-metadata": "Vous n’avez pas le droit d’afficher les métadonnées des fichiers supprimés.",
+       "apierror-cantview-deleted-revision-content": "Vous n’avez pas la permission de visualiser le contenu des révisions supprimées.",
        "apierror-changeauth-norequest": "Échec à la création de la requête de modification.",
        "apierror-chunk-too-small": "La taille minimale d’un segment est de $1 {{PLURAL:$1|octet|octets}} pour les segments hors le dernier.",
        "apierror-cidrtoobroad": "Les plages CIDR $1 plus large que /$2 ne sont pas acceptées.",
        "apierror-invalidsection": "Le paramètre <var>section</var> doit être un ID de section valide ou <kbd>new</kbd>.",
        "apierror-invalidsha1base36hash": "Le hachage SHA1Base36 fourni n’est pas valide.",
        "apierror-invalidsha1hash": "Le hachage SHA1 fourni n’est pas valide.",
-       "apierror-invalidtitle": "Mauvais titre « $1 ».",
+       "apierror-invalidtitle": "Mauvais titre « $1 ».",
        "apierror-invalidurlparam": "Valeur non valide pour <var>$1urlparam</var> (<kbd>$2=$3</kbd>).",
        "apierror-invaliduser": "Nom d'utilisateur invalide \"$1\".",
        "apierror-invaliduserid": "L'ID d'utilisateur <var>$1</var> n'est pas valide.",
        "apierror-paramempty": "Le paramètre <var>$1</var> ne peut pas être vide.",
        "apierror-parsetree-notwikitext": "<kbd>prop=parsetree</kbd> n’est pris en charge que pour le contenu wikitexte.",
        "apierror-parsetree-notwikitext-title": "<kbd>prop=parsetree</kbd> n’est pris en charge que pour le contenu wikitexte. $1 utilise le modèle de contenu $2.",
-       "apierror-pastexpiry": "La date d’expiration « $1 » est dépassée.",
+       "apierror-pastexpiry": "La date d’expiration « $1 » est dépassée.",
        "apierror-permissiondenied": "Vous n’avez pas le droit de $1.",
        "apierror-permissiondenied-generic": "Autorisation refusée.",
        "apierror-permissiondenied-patrolflag": "Vous avez besoin du droit <code>patrol</code> ou <code>patrolmarks</code> pour demander le drapeau patrouillé.",
        "apierror-permissiondenied-unblock": "Vous n’avez pas le droit de débloquer les utilisateurs.",
        "apierror-prefixsearchdisabled": "La recherche de préfixe est désactivée en mode misérable.",
        "apierror-promised-nonwrite-api": "L’entête HTTP <code>Promise-Non-Write-API-Action</code> ne peut pas être envoyé aux modules de l’API en mode écriture.",
-       "apierror-protect-invalidaction": "Type de protection non valide « $1 ».",
-       "apierror-protect-invalidlevel": "Niveau de protection non valide « $1 ».",
+       "apierror-protect-invalidaction": "Type de protection non valide « $1 ».",
+       "apierror-protect-invalidlevel": "Niveau de protection non valide « $1 ».",
        "apierror-ratelimited": "Vous avez dépassé votre limite de débit. Veuillez attendre un peu et réessayer.",
        "apierror-readapidenied": "Vous avez besoin du droit de lecture pour utiliser ce module.",
        "apierror-readonly": "Ce wiki est actuellement en mode lecture seule.",
        "apiwarn-deprecation-login-token": "La récupération d’un jeton via <kbd>action=login</kbd> est désuète. Utilisez <kbd>action=query&meta=tokens&type=login</kbd> à la place.",
        "apiwarn-deprecation-missingparam": "Comme <var>$1</var> n’a pas été spécifié, un format ancien a été utilisé pour la sortie. Ce format est obsolète, et dans le futur, le nouveau format sera toujours utilisé.",
        "apiwarn-deprecation-parameter": "Le paramètre <var>$1</var> est désuet.",
-       "apiwarn-deprecation-parse-headitems": "<kbd>prop=headitems</kbd> est désuet 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-parse-headitems": "<kbd>prop=headitems</kbd> est désuet depuis MediaWiki 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-post-without-content-type": "Une requête POST a été faite sans entête <code>Content-Type</code>. Cela ne fonctionne pas de façon fiable.",
        "apiwarn-deprecation-purge-get": "L’utilisation de <kbd>action=purge</kbd> via un GET est désuète. Utiliser POST à la place.",
        "apiwarn-deprecation-withreplacement": "<kbd>$1</kbd> est désuet. 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-ignoring-invalid-templated-value": "Ignorer la valeur <kbd>$2</kbd> dans <var>$1</var> en traitant les paramètres de modèle.",
-       "apiwarn-invalidcategory": "« $1 » n'est pas une catégorie.",
-       "apiwarn-invalidtitle": "« $1 » n’est pas un titre valide.",
+       "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-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-revidwithouttext": "<var>revid</var> utilisé sans <var>text</var>, et les propriétés de la page analysée ont été demandées. Vouliez-vous utiliser <var>oldid</var> au lieu de <var>revid</var> ?",
        "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-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-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> est 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-unclearnowtimestamp": "Passer « $2 » comme paramètre d’horodatage <var>$1</var> est 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).",
index e29c34a..9d5d349 100644 (file)
        "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-bad-badfilecontexttitle": "Titolo non valido nel parametro <var>$1badfilecontexttitle</var>.",
+       "apierror-cantview-deleted-description": "Non si dispone dei permessi necessari per vedere le descrizioni dei file cancellati.",
+       "apierror-cantview-deleted-metadata": "Non si dispone dei permessi necessari per vedere i metadati dei file cancellati.",
+       "apierror-cantview-deleted-revision-content": "Non si dispone dei permessi necessari per vedere il contenuto delle versioni cancellate.",
        "apierror-compare-notext": "Il parametro <var>$1</var> non può essere usato senza <var>$2</var>.",
        "apierror-invalidoldimage": "Il parametro <var>oldimage</var> ha un formato non valido.",
        "apierror-invaliduserid": "L'ID utente <var>$1</var> non è valido.",
index c029636..6124066 100644 (file)
        "apierror-cantimport-upload": "업로드된 페이지를 가져올 권한이 없습니다.",
        "apierror-cantimport": "페이지를 가져올 권한이 없습니다.",
        "apierror-cantsend": "로그인하지 않았거나 인증된 이메일 주소가 없거나 다른 사용자로 이메일을 보낼 권한이 없기 때문에 이메일을 보낼 수 없습니다.",
+       "apierror-cantview-deleted-description": "삭제된 파일의 설명을 볼 권한이 없습니다.",
+       "apierror-cantview-deleted-metadata": "삭제된 파일의 메타데이터를 볼 권한이 없습니다.",
        "apierror-compare-maintextrequired": "<var>$1slots</var>에 <kbd>main</kbd>이 포함되어 있다면 <var>$1text-main</var> 변수는 필수입니다. (메인 슬롯을 삭제할 수 없습니다)",
        "apierror-compare-notext": "<var>$1</var> 변수는 <var>$2</var> 없이 사용할 수 없습니다.",
        "apierror-emptynewsection": "비어있는 새 문단을 만들 수 없습니다.",
index 59553e9..59eb62c 100644 (file)
        "apierror-cantchangecontentmodel": "Немате дозвола за менување содржинскиот модел на страница.",
        "apierror-cantimport-upload": "Немате дозвола да увезувате подигнати страници.",
        "apierror-cantimport": "Немате дозвола за увезуваање страници.",
+       "apierror-cantview-deleted-comment": "Немате дозвола за прегледување на избришаните коментари.",
+       "apierror-cantview-deleted-description": "Немате дозвола за прегледување описи на избришаните податотеки.",
+       "apierror-cantview-deleted-metadata": "Немате дозвола за прегледување метаподатоци на избришаните податотеки.",
+       "apierror-cantview-deleted-revision-content": "Немате дозвола за прегледување содржина на избришаните преработки.",
        "apierror-copyuploadbaddomain": "Подигањето преку URL не е дозволено од овој домен.",
        "apierror-copyuploadbadurl": "Подигањето не е дозволено од оваа URL-адреса.",
        "apierror-emptynewsection": "Создавањето на нови празни поднаслови не е дозволено.",
index e71a9dc..65a0913 100644 (file)
@@ -17,7 +17,8 @@
                        "InternerowyGołąb",
                        "CiaPan",
                        "Vlad5250",
-                       "Railfail536"
+                       "Railfail536",
+                       "Rail"
                ]
        },
        "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Dokumentacja]]\n* [[mw:Special:MyLanguage/API:FAQ|FAQ]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Lista dyskusyjna]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Ogłoszenia dotyczące API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Błędy i propozycje]\n</div>\n<strong>Stan:</strong> Wszystkie funkcje opisane na tej stronie powinny działać, ale API nadal jest aktywnie rozwijane i mogą się zmienić w dowolnym czasie. Subskrybuj [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ listę dyskusyjną mediawiki-api-announce], aby móc na bieżąco dowiadywać się o aktualizacjach.\n\n<strong>Błędne żądania:</strong> Gdy zostanie wysłane błędne żądanie do API, zostanie wysłany w odpowiedzi nagłówek HTTP z kluczem \"MediaWiki-API-Error\" i zarówno jego wartość jak i wartość kodu błędu wysłanego w odpowiedzi będą miały taką samą wartość. Aby uzyskać więcej informacji, zobacz [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Błędy i ostrzeżenia]].\n\n<strong>Testowanie:</strong> Aby łatwo testować żądania API, zobacz [[Special:ApiSandbox]].",
        "apierror-cantimport": "Nie masz uprawnień do importowania stron.",
        "apierror-cantsend": "Nie jesteś zalogowany, nie masz potwierdzonego adresu e-mail, albo nie masz prawa wysyłać e-maili do innych użytkowników, więc nie możesz wysłać wiadomości e-mail.",
        "apierror-cantundelete": "Nie można przywrócić: dana wersja nie istnieje albo została już przywrócona.",
+       "apierror-cantview-deleted-comment": "Nie masz uprawnień do podglądu usuniętych komentarzy.",
+       "apierror-cantview-deleted-description": "Nie masz uprawnień do podglądu opisów usuniętych plików.",
+       "apierror-cantview-deleted-metadata": "Nie masz uprawnień do podglądu metadanych usuniętych plików.",
+       "apierror-cantview-deleted-revision-content": "Nie masz uprawnień do podglądu treści usuniętych wersji.",
        "apierror-exceptioncaught": "[$1] Stwierdzono wyjątek: $2",
        "apierror-filedoesnotexist": "Plik nie istnieje.",
        "apierror-import-unknownerror": "Nieznany błąd podczas importowania: $1.",
index 6e2c1f1..77f927d 100644 (file)
        "apierror-cantoverwrite-sharedfile": "O arquivo de destino existe em um repositório compartilhado e você não tem permissão para substituí-lo.",
        "apierror-cantsend": "Você não está logado, não possui um endereço de e-mail confirmado ou não tem permissão para enviar e-mails para outros usuários, por isso não pode enviar e-mails.",
        "apierror-cantundelete": "Não foi possível recuperar arquivos: as revisões solicitadas podem não existir ou talvez já tenham sido eliminadas.",
+       "apierror-cantview-deleted-comment": "Você não tem permissão para visualizar comentários excluídos.",
+       "apierror-cantview-deleted-description": "Você não tem permissão para visualizar descrições de arquivos excluídos.",
+       "apierror-cantview-deleted-metadata": "Você não tem permissão para visualizar os metadados dos arquivos excluídos.",
+       "apierror-cantview-deleted-revision-content": "Você não tem permissão para visualizar o conteúdo das revisões excluídas.",
        "apierror-changeauth-norequest": "Falha ao criar pedido de mudança.",
        "apierror-chunk-too-small": "O tamanho mínimo do bloco é $1 {{PLURAL:$1|byte|bytes}} para os pedaços não finais.",
        "apierror-cidrtoobroad": "Os intervalos CIDR $1 maiores que /$2 não são aceitos.",
index 87f056b..b648443 100644 (file)
        "apierror-cantoverwrite-sharedfile": "{{doc-apierror}}",
        "apierror-cantsend": "{{doc-apierror}}",
        "apierror-cantundelete": "{{doc-apierror}}",
+       "apierror-cantview-deleted-comment": "{{doc-apierror}}",
+       "apierror-cantview-deleted-description": "{{doc-apierror}}",
+       "apierror-cantview-deleted-metadata": "{{doc-apierror}}",
+       "apierror-cantview-deleted-revision-content": "{{doc-apierror}}",
        "apierror-changeauth-norequest": "{{doc-apierror}}",
        "apierror-chunk-too-small": "{{doc-apierror}}\n\nParameters:\n* $1 - Minimum size in bytes.",
        "apierror-cidrtoobroad": "{{doc-apierror}}\n\nParameters:\n* $1 - \"IPv4\" or \"IPv6\"\n* $2 - Minimum CIDR mask length.",
index c91976f..4d02204 100644 (file)
@@ -37,7 +37,8 @@
                        "Edward Chernenko",
                        "Vlad5250",
                        "Diralik",
-                       "DmitTrix"
+                       "DmitTrix",
+                       "Марио"
                ]
        },
        "apihelp-main-extended-description": "<div class=\"hlist plainlinks api-main-links\">\n* [[mw:Special:MyLanguage/API:Main_page|Документация]]\n* [[mw:Special:MyLanguage/API:FAQ|ЧаВО]]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api Почтовая рассылка]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-api-announce Новости API]\n* [https://phabricator.wikimedia.org/maniphest/query/GebfyV4uCaLd/#R Ошибки и запросы]\n</div>\n<strong>Статус:</strong> MediaWiki API — зрелый и стабильный интерфейс, активно поддерживаемый и улучшаемый. Мы стараемся избегать ломающих изменений, однако изредка они могут быть необходимы. Подпишитесь на [https://lists.wikimedia.org/pipermail/mediawiki-api-announce/ почтовую рассылку mediawiki-api-announce], чтобы быть в курсе обновлений.\n\n<strong>Ошибочные запросы:</strong> Если API получает запрос с ошибкой, вернётся заголовок HTTP с ключом «MediaWiki-API-Error», после чего значение заголовка и код ошибки будут отправлены обратно и установлены в то же значение. Более подробную информацию см. [[mw:Special:MyLanguage/API:Errors_and_warnings|API: Ошибки и предупреждения]].\n\n<p class=\"mw-apisandbox-link\"><strong>Тестирование:</strong> для удобства тестирования API-запросов, см. [[Special:ApiSandbox]].</p>",
@@ -94,6 +95,7 @@
        "apihelp-compare-param-fromid": "Идентификатор первой сравниваемой страницы.",
        "apihelp-compare-param-fromrev": "Первая сравниваемая версия.",
        "apihelp-compare-param-frompst": "Выполнить преобразование перед записью правки (PST) над <var>fromtext-&#x7B;slot}</var>.",
+       "apihelp-compare-param-fromslots": "Переопределение содержимого версии, заданной параметром <var>fromtitle</var>, <var>fromid</var> или <var>fromrev</var>.\n\nЭтот параметр определяет слоты, которые должны быть изменены. Используйте <var>fromtext-&#x7B;slot}</var>, <var>fromcontentmodel-&#x7B;slot}</var>, и <var>fromcontentformat-&#x7B;slot}</var> для определения содержимого для каждого слота.",
        "apihelp-compare-param-fromtext": "Укажите <kbd>fromslots=main</kbd> и используйте <var>fromtext-main</var>.",
        "apihelp-compare-param-fromcontentmodel": "Укажите <kbd>fromslots=main</kbd> и используйте <var>fromcontentmodel-main</var>.",
        "apihelp-compare-param-fromcontentformat": "Укажите <kbd>fromslots=main</kbd> и используйте <var>fromcontentformat-main</var>.",
        "apihelp-query+blocks-paramvalue-prop-reason": "Добавляет причину блокировки.",
        "apihelp-query+blocks-paramvalue-prop-range": "Добавляет диапазон IP-адресов, затронутых блокировкой.",
        "apihelp-query+blocks-paramvalue-prop-flags": "Добавляет бану метку (autoblock, anonoly, и так далее).",
+       "apihelp-query+blocks-paramvalue-prop-restrictions": "Добавляет ограничения частичных блокировок, если блокировка не действует во всём проекте.",
        "apihelp-query+blocks-param-show": "Показать только элементы, удовлетворяющие этим критериям.\nНапример, чтобы отобразить только бессрочные блокировки IP-адресов, установите <kbd>$1show=ip|!temp</kbd>.",
        "apihelp-query+blocks-example-simple": "Список блокировок.",
        "apihelp-query+blocks-example-users": "Список блокировок участников <kbd>Alice</kbd> и <kbd>Bob</kbd>.",
        "apierror-bad-watchlist-token": "Предоставлен некорректный токен списка наблюдения. Пожалуйста, установите корректный токен в [[Special:Preferences]].",
        "apierror-blockedfrommail": "Отправка электронной почты была для вас заблокирована.",
        "apierror-blocked": "Редактирование было для вас заблокировано.",
+       "apierror-blocked-partial": "Вы были заблокированы от редактирования этой страницы.",
        "apierror-botsnotsupported": "Этот интерфейс не поддерживается для ботов.",
        "apierror-cannot-async-upload-file": "Параметры <var>async</var> и <var>file</var> не могут применяться вместе. Если вы хотите ассинхронно обработать загруженный файл, сначала загрузите его во временное хранилище (используя параметр <var>stash</var>), а затем опубликуйте этот файл ассинхронно (используя параметры <var>filekey</var> и <var>async</var>).",
        "apierror-cannotreauthenticate": "Это действие недоступно, так как ваша личность не может быть подтверждена.",
index 14a7717..7ee3751 100644 (file)
        "apierror-cantoverwrite-sharedfile": "目標檔案存在於分享儲存庫上,因此您沒有權限來覆蓋掉。",
        "apierror-cantsend": "您尚未登入,您沒有已確認的電子郵件地址,或是您未被允許發送電子郵件給其他人,因此您不能發送電子郵件。",
        "apierror-cantundelete": "無法取消刪除:請求的修訂可能不存在,或是可能已被取消刪除。",
+       "apierror-cantview-deleted-description": "您沒有權限來檢視被刪除檔案的描述內容。",
+       "apierror-cantview-deleted-metadata": "您沒有權限來檢視被刪除檔案的詮釋資料。",
        "apierror-changeauth-norequest": "建立更改請求失敗。",
        "apierror-chunk-too-small": "對於非最終塊,最小塊的大小為 $1 {{PLURAL:$1|位元組|位元組}}。",
        "apierror-cidrtoobroad": "不能接受超出 /$2 的 $1 CIDR 範圍。",
index e7527d1..bc70d5e 100644 (file)
@@ -247,12 +247,18 @@ abstract class AuthenticationRequest {
 
        /**
         * Select a request by class name.
+        *
+        * @codingStandardsIgnoreStart
+        * @phan-template T
+        * @codingStandardsIgnoreEnd
         * @param AuthenticationRequest[] $reqs
         * @param string $class Class name
+        * @phan-param class-string<T> $class
         * @param bool $allowSubclasses If true, also returns any request that's a subclass of the given
         *   class.
         * @return AuthenticationRequest|null Returns null if there is not exactly
         *  one matching request.
+        * @phan-return T|null
         */
        public static function getRequestByClass( array $reqs, $class, $allowSubclasses = false ) {
                $requests = array_filter( $reqs, function ( $req ) use ( $class, $allowSubclasses ) {
index c831fc8..25a1754 100644 (file)
@@ -96,7 +96,9 @@ class ResetPasswordSecondaryAuthenticationProvider extends AbstractSecondaryAuth
                        }
                }
 
+               /** @var PasswordAuthenticationRequest $needReq */
                $needReq = $data->req ?? new PasswordAuthenticationRequest();
+               '@phan-var PasswordAuthenticationRequest $needReq';
                if ( !$needReq->action ) {
                        $needReq->action = AuthManager::ACTION_CHANGE;
                }
index e27ebac..2e20529 100644 (file)
@@ -41,16 +41,6 @@ use Wikimedia\IPSet;
  * @since 1.34 Refactored from User and Block.
  */
 class BlockManager {
-       // TODO: This should be UserIdentity instead of User
-       /** @var User */
-       private $currentUser;
-
-       /** @var WebRequest */
-       private $currentRequest;
-
-       /** @var PermissionManager */
-       private $permissionManager;
-
        /**
         * TODO Make this a const when HHVM support is dropped (T192166)
         *
@@ -71,20 +61,14 @@ class BlockManager {
 
        /**
         * @param ServiceOptions $options
-        * @param User $currentUser
-        * @param WebRequest $currentRequest
         * @param PermissionManager $permissionManager
         */
        public function __construct(
                ServiceOptions $options,
-               User $currentUser,
-               WebRequest $currentRequest,
                PermissionManager $permissionManager
        ) {
                $options->assertRequiredOptions( self::$constructorOptions );
                $this->options = $options;
-               $this->currentUser = $currentUser;
-               $this->currentRequest = $currentRequest;
                $this->permissionManager = $permissionManager;
        }
 
@@ -93,51 +77,116 @@ class BlockManager {
         * return a composite block that combines the strictest features of the applicable
         * blocks.
         *
-        * TODO: $user should be UserIdentity instead of User
+        * Different blocks may be sought, depending on the user and their permissions. The
+        * user may be:
+        * (1) The global user (and can be affected by IP blocks). The global request object
+        * is needed for checking the IP address, the XFF header and the cookies.
+        * (2) The global user (and exempt from IP blocks). The global request object is
+        * needed for checking the cookies.
+        * (3) Another user (not the global user). No request object is available or needed;
+        * just look for a block against the user account.
+        *
+        * Cases #1 and #2 check whether the global user is blocked in practice; the block
+        * may due to their user account being blocked or to an IP address block or cookie
+        * block (or multiple of these). Case #3 simply checks whether a user's account is
+        * blocked, and does not determine whether the person using that account is affected
+        * in practice by any IP address or cookie blocks.
         *
         * @internal This should only be called by User::getBlockedStatus
         * @param User $user
+        * @param WebRequest|null $request The global request object if the user is the
+        *  global user (cases #1 and #2), otherwise null (case #3). The IP address and
+        *  information from the request header are needed to find some types of blocks.
         * @param bool $fromReplica Whether to check the replica DB first.
         *  To improve performance, non-critical checks are done against replica DBs.
         *  Check when actually saving should be done against master.
         * @return AbstractBlock|null The most relevant block, or null if there is no block.
         */
-       public function getUserBlock( User $user, $fromReplica ) {
-               $isAnon = $user->getId() === 0;
+       public function getUserBlock( User $user, $request, $fromReplica ) {
                $fromMaster = !$fromReplica;
+               $ip = null;
 
-               // TODO: If $user is the current user, we should use the current request. Otherwise,
-               // we should not look for XFF or cookie blocks.
-               $request = $user->getRequest();
+               // If this is the global user, they may be affected by IP blocks (case #1),
+               // or they may be exempt (case #2). If affected, look for additional blocks
+               // against the IP address.
+               $checkIpBlocks = $request &&
+                       !$this->permissionManager->userHasRight( $user, 'ipblock-exempt' );
 
-               # We only need to worry about passing the IP address to the block generator if the
-               # user is not immune to autoblocks/hardblocks, and they are the current user so we
-               # know which IP address they're actually coming from
-               $ip = null;
-               $sessionUser = $this->currentUser;
-               // the session user is set up towards the end of Setup.php. Until then,
-               // assume it's a logged-out user.
-               $globalUserName = $sessionUser->isSafeToLoad()
-                       ? $sessionUser->getName()
-                       : IP::sanitizeIP( $this->currentRequest->getIP() );
-               if ( $user->getName() === $globalUserName &&
-                        !$this->permissionManager->userHasRight( $user, 'ipblock-exempt' ) ) {
-                       $ip = $this->currentRequest->getIP();
+               if ( $request && $checkIpBlocks ) {
+
+                       // Case #1: checking the global user, including IP blocks
+                       $ip = $request->getIP();
+                       // TODO: remove dependency on DatabaseBlock (T221075)
+                       $blocks = DatabaseBlock::newListFromTarget( $user, $ip, $fromMaster );
+                       $this->getAdditionalIpBlocks( $blocks, $request, !$user->isRegistered(), $fromMaster );
+                       $this->getCookieBlock( $blocks, $user, $request );
+
+               } elseif ( $request ) {
+
+                       // Case #2: checking the global user, but they are exempt from IP blocks
+                       // TODO: remove dependency on DatabaseBlock (T221075)
+                       $blocks = DatabaseBlock::newListFromTarget( $user, null, $fromMaster );
+                       $this->getCookieBlock( $blocks, $user, $request );
+
+               } else {
+
+                       // Case #3: checking whether a user's account is blocked
+                       // TODO: remove dependency on DatabaseBlock (T221075)
+                       $blocks = DatabaseBlock::newListFromTarget( $user, null, $fromMaster );
+
+               }
+
+               // Filter out any duplicated blocks, e.g. from the cookie
+               $blocks = $this->getUniqueBlocks( $blocks );
+
+               $block = null;
+               if ( count( $blocks ) > 0 ) {
+                       if ( count( $blocks ) === 1 ) {
+                               $block = $blocks[ 0 ];
+                       } else {
+                               $block = new CompositeBlock( [
+                                       'address' => $ip,
+                                       'byText' => 'MediaWiki default',
+                                       'reason' => wfMessage( 'blockedtext-composite-reason' )->plain(),
+                                       'originalBlocks' => $blocks,
+                               ] );
+                       }
                }
 
-               // User/IP blocking
-               // After this, $blocks is an array of blocks or an empty array
-               // TODO: remove dependency on DatabaseBlock
-               $blocks = DatabaseBlock::newListFromTarget( $user, $ip, $fromMaster );
+               Hooks::run( 'GetUserBlock', [ clone $user, $ip, &$block ] );
+
+               return $block;
+       }
 
-               // Cookie blocking
+       /**
+        * Get the cookie block, if there is one.
+        *
+        * @param AbstractBlock[] &$blocks
+        * @param UserIdentity $user
+        * @param WebRequest $request
+        * @return void
+        */
+       private function getCookieBlock( &$blocks, UserIdentity $user, WebRequest $request ) {
                $cookieBlock = $this->getBlockFromCookieValue( $user, $request );
-               if ( $cookieBlock instanceof AbstractBlock ) {
+               if ( $cookieBlock instanceof DatabaseBlock ) {
                        $blocks[] = $cookieBlock;
                }
+       }
+
+       /**
+        * Check for any additional blocks against the IP address or any IPs in the XFF header.
+        *
+        * @param AbstractBlock[] &$blocks Blocks found so far
+        * @param WebRequest $request
+        * @param bool $isAnon The user is logged out
+        * @param bool $fromMaster
+        * @return void
+        */
+       private function getAdditionalIpBlocks( &$blocks, WebRequest $request, $isAnon, $fromMaster ) {
+               $ip = $request->getIP();
 
                // Proxy blocking
-               if ( $ip !== null && !in_array( $ip, $this->options->get( 'ProxyWhitelist' ) ) ) {
+               if ( !in_array( $ip, $this->options->get( 'ProxyWhitelist' ) ) ) {
                        // Local list
                        if ( $this->isLocallyBlockedProxy( $ip ) ) {
                                $blocks[] = new SystemBlock( [
@@ -156,24 +205,8 @@ class BlockManager {
                        }
                }
 
-               // (T25343) Apply IP blocks to the contents of XFF headers, if enabled
-               if ( $this->options->get( 'ApplyIpBlocksToXff' )
-                       && $ip !== null
-                       && !in_array( $ip, $this->options->get( 'ProxyWhitelist' ) )
-               ) {
-                       $xff = $request->getHeader( 'X-Forwarded-For' );
-                       $xff = array_map( 'trim', explode( ',', $xff ) );
-                       $xff = array_diff( $xff, [ $ip ] );
-                       // TODO: remove dependency on DatabaseBlock
-                       $xffblocks = DatabaseBlock::getBlocksForIPList( $xff, $isAnon, $fromMaster );
-                       $blocks = array_merge( $blocks, $xffblocks );
-               }
-
                // Soft blocking
-               if ( $ip !== null
-                       && $isAnon
-                       && IP::isInRanges( $ip, $this->options->get( 'SoftBlockRanges' ) )
-               ) {
+               if ( $isAnon && IP::isInRanges( $ip, $this->options->get( 'SoftBlockRanges' ) ) ) {
                        $blocks[] = new SystemBlock( [
                                'address' => $ip,
                                'byText' => 'MediaWiki default',
@@ -183,26 +216,17 @@ class BlockManager {
                        ] );
                }
 
-               // Filter out any duplicated blocks, e.g. from the cookie
-               $blocks = $this->getUniqueBlocks( $blocks );
-
-               $block = null;
-               if ( count( $blocks ) > 0 ) {
-                       if ( count( $blocks ) === 1 ) {
-                               $block = $blocks[ 0 ];
-                       } else {
-                               $block = new CompositeBlock( [
-                                       'address' => $ip,
-                                       'byText' => 'MediaWiki default',
-                                       'reason' => wfMessage( 'blockedtext-composite-reason' )->plain(),
-                                       'originalBlocks' => $blocks,
-                               ] );
-                       }
+               // (T25343) Apply IP blocks to the contents of XFF headers, if enabled
+               if ( $this->options->get( 'ApplyIpBlocksToXff' )
+                       && !in_array( $ip, $this->options->get( 'ProxyWhitelist' ) )
+               ) {
+                       $xff = $request->getHeader( 'X-Forwarded-For' );
+                       $xff = array_map( 'trim', explode( ',', $xff ) );
+                       $xff = array_diff( $xff, [ $ip ] );
+                       // TODO: remove dependency on DatabaseBlock (T221075)
+                       $xffblocks = DatabaseBlock::getBlocksForIPList( $xff, $isAnon, $fromMaster );
+                       $blocks = array_merge( $blocks, $xffblocks );
                }
-
-               Hooks::run( 'GetUserBlock', [ clone $user, $ip, &$block ] );
-
-               return $block;
        }
 
        /**
@@ -255,7 +279,7 @@ class BlockManager {
 
                $blockCookieId = $this->getIdFromCookieValue( $cookieValue );
                if ( !is_null( $blockCookieId ) ) {
-                       // TODO: remove dependency on DatabaseBlock
+                       // TODO: remove dependency on DatabaseBlock (T221075)
                        $block = DatabaseBlock::newFromID( $blockCookieId );
                        if (
                                $block instanceof DatabaseBlock &&
index 6007abd..b1a8e21 100644 (file)
@@ -24,7 +24,6 @@ namespace MediaWiki\Block;
 
 use ActorMigration;
 use AutoCommitUpdate;
-use BadMethodCallException;
 use CommentStore;
 use DeferredUpdates;
 use Hooks;
@@ -161,47 +160,6 @@ class DatabaseBlock extends AbstractBlock {
                }
        }
 
-       /**
-        * Return the list of ipblocks fields that should be selected to create
-        * a new block.
-        * @deprecated since 1.31, use self::getQueryInfo() instead.
-        * @return array
-        */
-       public static function selectFields() {
-               global $wgActorTableSchemaMigrationStage;
-
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->ipb_by or $row->ipb_by_text and we can't give it
-                       // useful values here once those aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               wfDeprecated( __METHOD__, '1.31' );
-               return [
-                       'ipb_id',
-                       'ipb_address',
-                       'ipb_by',
-                       'ipb_by_text',
-                       'ipb_by_actor' => 'NULL',
-                       'ipb_timestamp',
-                       'ipb_auto',
-                       'ipb_anon_only',
-                       'ipb_create_account',
-                       'ipb_enable_autoblock',
-                       'ipb_expiry',
-                       'ipb_deleted',
-                       'ipb_block_email',
-                       'ipb_allow_usertalk',
-                       'ipb_parent_block_id',
-                       'ipb_sitewide',
-               ] + CommentStore::getStore()->getFields( 'ipb_reason' );
-       }
-
        /**
         * Return the tables, fields, and join conditions to be selected to create
         * a new block object.
index 8018117..b2f2452 100644 (file)
@@ -89,6 +89,7 @@ class LinkCache {
         *
         * @param bool|null $update
         * @return bool
+        * @deprecated Since 1.34
         */
        public function forUpdate( $update = null ) {
                return wfSetVar( $this->mForUpdate, $update );
index 8f816d9..bc0bbfa 100644 (file)
@@ -78,8 +78,6 @@ class UserCache {
         * @param string $caller The calling method
         */
        public function doQuery( array $userIds, $options = [], $caller = '' ) {
-               global $wgActorTableSchemaMigrationStage;
-
                $usersToCheck = [];
                $usersToQuery = [];
 
@@ -100,21 +98,12 @@ class UserCache {
                // Lookup basic info for users not yet loaded...
                if ( count( $usersToQuery ) ) {
                        $dbr = wfGetDB( DB_REPLICA );
-                       $tables = [ 'user' ];
+                       $tables = [ 'user', 'actor' ];
                        $conds = [ 'user_id' => $usersToQuery ];
-                       $fields = [ 'user_name', 'user_real_name', 'user_registration', 'user_id' ];
-                       $joinConds = [];
-
-                       // Technically we shouldn't allow this without SCHEMA_COMPAT_READ_NEW,
-                       // but it does little harm and might be needed for write callers loading a User.
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_NEW ) {
-                               $tables[] = 'actor';
-                               $fields[] = 'actor_id';
-                               $joinConds['actor'] = [
-                                       ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) ? 'JOIN' : 'LEFT JOIN',
-                                       [ 'actor_user = user_id' ]
-                               ];
-                       }
+                       $fields = [ 'user_name', 'user_real_name', 'user_registration', 'user_id', 'actor_id' ];
+                       $joinConds = [
+                               'actor' => [ 'JOIN', 'actor_user = user_id' ],
+                       ];
 
                        $comment = __METHOD__;
                        if ( strval( $caller ) !== '' ) {
@@ -127,9 +116,7 @@ class UserCache {
                                $this->cache[$userId]['name'] = $row->user_name;
                                $this->cache[$userId]['real_name'] = $row->user_real_name;
                                $this->cache[$userId]['registration'] = $row->user_registration;
-                               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_NEW ) {
-                                       $this->cache[$userId]['actor'] = $row->actor_id;
-                               }
+                               $this->cache[$userId]['actor'] = $row->actor_id;
                                $usersToCheck[$userId] = $row->user_name;
                        }
                }
index 88a7042..a79325a 100644 (file)
@@ -27,18 +27,20 @@ use Wikimedia\Rdbms\DBQueryError;
  * This will work on any MediaWiki installation.
  */
 class LCStoreDB implements LCStore {
-       /** @var string */
-       private $currentLang;
-       /** @var bool */
-       private $writesDone = false;
+       /** @var string Language code */
+       private $code;
+       /** @var array Server configuration map */
+       private $server;
+
+       /** @var array Rows buffered for insertion */
+       private $batch = [];
+
        /** @var IDatabase|null */
        private $dbw;
-       /** @var array */
-       private $batch = [];
-       /** @var bool */
+       /** @var bool Whether a batch of writes were recently written */
+       private $writesDone = false;
+       /** @var bool Whether the DB is read-only or otherwise unavailable for writes */
        private $readOnly = false;
-       /** @var array Server configuration map */
-       private $server;
 
        public function __construct( $params ) {
                $this->server = $params['server'] ?? [];
@@ -74,14 +76,14 @@ class LCStoreDB implements LCStore {
                $dbw = $this->getWriteConnection();
                $this->readOnly = $dbw->isReadOnly();
 
-               $this->currentLang = $code;
+               $this->code = $code;
                $this->batch = [];
        }
 
        public function finishWrite() {
                if ( $this->readOnly ) {
                        return;
-               } elseif ( is_null( $this->currentLang ) ) {
+               } elseif ( is_null( $this->code ) ) {
                        throw new MWException( __CLASS__ . ': must call startWrite() before finishWrite()' );
                }
 
@@ -91,7 +93,7 @@ class LCStoreDB implements LCStore {
                        $dbw = $this->getWriteConnection();
                        $dbw->startAtomic( __METHOD__ );
                        try {
-                               $dbw->delete( 'l10n_cache', [ 'lc_lang' => $this->currentLang ], __METHOD__ );
+                               $dbw->delete( 'l10n_cache', [ 'lc_lang' => $this->code ], __METHOD__ );
                                foreach ( array_chunk( $this->batch, 500 ) as $rows ) {
                                        $dbw->insert( 'l10n_cache', $rows, __METHOD__ );
                                }
@@ -108,21 +110,21 @@ class LCStoreDB implements LCStore {
                        $trxProfiler->setSilenced( $oldSilenced );
                }
 
-               $this->currentLang = null;
+               $this->code = null;
                $this->batch = [];
        }
 
        public function set( $key, $value ) {
                if ( $this->readOnly ) {
                        return;
-               } elseif ( is_null( $this->currentLang ) ) {
+               } elseif ( is_null( $this->code ) ) {
                        throw new MWException( __CLASS__ . ': must call startWrite() before set()' );
                }
 
                $dbw = $this->getWriteConnection();
 
                $this->batch[] = [
-                       'lc_lang' => $this->currentLang,
+                       'lc_lang' => $this->code,
                        'lc_key' => $key,
                        'lc_value' => $dbw->encodeBlob( serialize( $value ) )
                ];
index 2ef9c9f..14e391d 100644 (file)
@@ -1,5 +1,6 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
 use MediaWiki\Storage\RevisionRecord;
 
 /**
@@ -273,11 +274,15 @@ class CategoryMembershipChange {
         * @return null|string
         */
        private function getPreviousRevisionTimestamp() {
-               $previousRev = Revision::newFromId(
-                               $this->pageTitle->getPreviousRevisionID( $this->pageTitle->getLatestRevID() )
-                       );
-
-               return $previousRev ? $previousRev->getTimestamp() : null;
+               $rl = MediaWikiServices::getInstance()->getRevisionLookup();
+               $latestRev = $rl->getRevisionByTitle( $this->pageTitle );
+               if ( $latestRev ) {
+                       $previousRev = $rl->getPreviousRevision( $latestRev );
+                       if ( $previousRev ) {
+                               return $previousRev->getTimestamp();
+                       }
+               }
+               return null;
        }
 
 }
index d448eae..a048a22 100644 (file)
@@ -109,11 +109,11 @@ class RCCacheEntryFactory {
        }
 
        /**
-        * @param RecentChange $cacheEntry
+        * @param RCCacheEntry $cacheEntry
         *
         * @return string
         */
-       private function buildCLink( RecentChange $cacheEntry ) {
+       private function buildCLink( RCCacheEntry $cacheEntry ) {
                $type = $cacheEntry->mAttribs['rc_type'];
 
                // New unpatrolled pages
index 1d590d9..e184825 100644 (file)
@@ -221,55 +221,6 @@ class RecentChange implements Taggable {
                }
        }
 
-       /**
-        * Return the list of recentchanges fields that should be selected to create
-        * a new recentchanges object.
-        * @deprecated since 1.31, use self::getQueryInfo() instead.
-        * @return array
-        */
-       public static function selectFields() {
-               global $wgActorTableSchemaMigrationStage;
-
-               wfDeprecated( __METHOD__, '1.31' );
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->rc_user or $row->rc_user_text and we can't give it
-                       // useful values here once those aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               return [
-                       'rc_id',
-                       'rc_timestamp',
-                       'rc_user',
-                       'rc_user_text',
-                       'rc_actor' => 'NULL',
-                       'rc_namespace',
-                       'rc_title',
-                       'rc_minor',
-                       'rc_bot',
-                       'rc_new',
-                       'rc_cur_id',
-                       'rc_this_oldid',
-                       'rc_last_oldid',
-                       'rc_type',
-                       'rc_source',
-                       'rc_patrolled',
-                       'rc_ip',
-                       'rc_old_len',
-                       'rc_new_len',
-                       'rc_deleted',
-                       'rc_logid',
-                       'rc_log_type',
-                       'rc_log_action',
-                       'rc_params',
-               ] + CommentStore::getStore()->getFields( 'rc_comment' );
-       }
-
        /**
         * Return the tables, fields, and join conditions to be selected to create
         * a new recentchanges object.
index 9ee000d..ba6cb2c 100644 (file)
@@ -524,9 +524,7 @@ class ChangeTags {
                                        ->userHasRight( $user, 'applychangetags' )
                        ) {
                                return Status::newFatal( 'tags-apply-no-permission' );
-                       } elseif ( $user->getBlock() ) {
-                               // @TODO Ensure that the block does not apply to the `applychangetags`
-                               //       right.
+                       } elseif ( $user->getBlock() && $user->getBlock()->isSitewide() ) {
                                return Status::newFatal( 'tags-apply-blocked', $user->getName() );
                        }
                }
@@ -601,9 +599,7 @@ class ChangeTags {
                                        ->userHasRight( $user, 'changetags' )
                        ) {
                                return Status::newFatal( 'tags-update-no-permission' );
-                       } elseif ( $user->getBlock() ) {
-                               // @TODO Ensure that the block does not apply to the `changetags`
-                               //       right.
+                       } elseif ( $user->getBlock() && $user->getBlock()->isSitewide() ) {
                                return Status::newFatal( 'tags-update-blocked', $user->getName() );
                        }
                }
@@ -1023,9 +1019,7 @@ class ChangeTags {
                                        ->userHasRight( $user, 'managechangetags' )
                        ) {
                                return Status::newFatal( 'tags-manage-no-permission' );
-                       } elseif ( $user->getBlock() ) {
-                               // @TODO Ensure that the block does not apply to the `managechangetags`
-                               //       right.
+                       } elseif ( $user->getBlock() && $user->getBlock()->isSitewide() ) {
                                return Status::newFatal( 'tags-manage-blocked', $user->getName() );
                        }
                }
@@ -1099,9 +1093,7 @@ class ChangeTags {
                                        ->userHasRight( $user, 'managechangetags' )
                        ) {
                                return Status::newFatal( 'tags-manage-no-permission' );
-                       } elseif ( $user->getBlock() ) {
-                               // @TODO Ensure that the block does not apply to the `managechangetags`
-                               //       right.
+                       } elseif ( $user->getBlock() && $user->getBlock()->isSitewide() ) {
                                return Status::newFatal( 'tags-manage-blocked', $user->getName() );
                        }
                }
@@ -1200,9 +1192,7 @@ class ChangeTags {
                                        ->userHasRight( $user, 'managechangetags' )
                        ) {
                                return Status::newFatal( 'tags-manage-no-permission' );
-                       } elseif ( $user->getBlock() ) {
-                               // @TODO Ensure that the block does not apply to the `managechangetags`
-                               //       right.
+                       } elseif ( $user->getBlock() && $user->getBlock()->isSitewide() ) {
                                return Status::newFatal( 'tags-manage-blocked', $user->getName() );
                        }
                }
@@ -1322,9 +1312,7 @@ class ChangeTags {
                                        ->userHasRight( $user, 'deletechangetags' )
                        ) {
                                return Status::newFatal( 'tags-delete-no-permission' );
-                       } elseif ( $user->getBlock() ) {
-                               // @TODO Ensure that the block does not apply to the `deletechangetags`
-                               //       right.
+                       } elseif ( $user->getBlock() && $user->getBlock()->isSitewide() ) {
                                return Status::newFatal( 'tags-manage-blocked', $user->getName() );
                        }
                }
index 6b5482c..dffe6e1 100644 (file)
@@ -191,11 +191,11 @@ class SquidPurgeClient {
        /**
         * Queue a purge operation
         *
-        * @param string $url
+        * @param string $url Fully expanded URL (with host and protocol)
         */
        public function queuePurge( $url ) {
                global $wgSquidPurgeUseHostHeader;
-               $url = CdnCacheUpdate::expand( str_replace( "\n", '', $url ) );
+               $url = str_replace( "\n", '', $url ); // sanity
                $request = [];
                if ( $wgSquidPurgeUseHostHeader ) {
                        $url = wfParseUrl( $url );
diff --git a/includes/composer/ComposerPhpunitXmlCoverageEdit.php b/includes/composer/ComposerPhpunitXmlCoverageEdit.php
new file mode 100644 (file)
index 0000000..7db4b11
--- /dev/null
@@ -0,0 +1,60 @@
+<?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.
+ *
+ */
+
+/**
+ * Edit phpunit.xml to speed up code coverage generation.
+ *
+ * Usage: composer phpunit:coverage-edit -- extensions/ExtensionName
+ *
+ * This class runs *outside* of the normal MediaWiki
+ * environment and cannot depend upon any MediaWiki
+ * code.
+ */
+class ComposerPhpunitXmlCoverageEdit {
+
+       public static function onEvent( $event ) {
+               $IP = dirname( dirname( __DIR__ ) );
+               // TODO: Support passing arbitrary directories for core (or extensions/skins).
+               $args = $event->getArguments();
+               if ( count( $args ) !== 1 ) {
+                       throw new InvalidArgumentException( 'Pass extensions/$extensionName as an argument, ' .
+                               'e.g. "composer phpunit:coverage-edit -- extensions/BoilerPlate"' );
+               }
+               $project = current( $args );
+               $phpunitXml = \PHPUnit\Util\Xml::loadFile( $IP . '/phpunit.xml.dist' );
+               $whitelist = iterator_to_array( $phpunitXml->getElementsByTagName( 'whitelist' ) );
+               /** @var DOMNode $childNode */
+               foreach ( $whitelist as $childNode ) {
+                       $childNode->parentNode->removeChild( $childNode );
+               }
+               $whitelistElement = $phpunitXml->createElement( 'whitelist' );
+               $whitelistElement->setAttribute( 'addUncoveredFilesFromWhitelist', 'false' );
+               // TODO: Use AutoloadClasses from extension.json to load the relevant directories
+               foreach ( [ 'includes', 'src', 'maintenance' ] as $dir ) {
+                       $dirElement = $phpunitXml->createElement( 'directory', $project . '/' . $dir );
+                       $dirElement->setAttribute( 'suffix', '.php' );
+                       $whitelistElement->appendChild( $dirElement );
+
+               }
+               $phpunitXml->getElementsByTagName( 'filter' )->item( 0 )
+                       ->appendChild( $whitelistElement );
+               $phpunitXml->formatOutput = true;
+               $phpunitXml->save( $IP . '/phpunit.xml' );
+       }
+}
index e6a856c..cbcaba1 100644 (file)
@@ -81,6 +81,12 @@ class RequestContext implements IContextSource, MutableContext {
         */
        private static $instance = null;
 
+       /**
+        * Boolean flag to guard against recursion in getLanguage
+        * @var bool
+        */
+       private $languageRecursion = false;
+
        /**
         * @param Config $config
         */
@@ -318,7 +324,7 @@ class RequestContext implements IContextSource, MutableContext {
         * @since 1.19
         */
        public function getLanguage() {
-               if ( isset( $this->recursion ) ) {
+               if ( $this->languageRecursion === true ) {
                        trigger_error( "Recursion detected in " . __METHOD__, E_USER_WARNING );
                        $e = new Exception;
                        wfDebugLog( 'recursion-guard', "Recursion detected:\n" . $e->getTraceAsString() );
@@ -326,7 +332,7 @@ class RequestContext implements IContextSource, MutableContext {
                        $code = $this->getConfig()->get( 'LanguageCode' ) ?: 'en';
                        $this->lang = Language::factory( $code );
                } elseif ( $this->lang === null ) {
-                       $this->recursion = true;
+                       $this->languageRecursion = true;
 
                        try {
                                $request = $this->getRequest();
@@ -348,7 +354,7 @@ class RequestContext implements IContextSource, MutableContext {
                                        $this->lang = $obj;
                                }
                        } finally {
-                               unset( $this->recursion );
+                               $this->languageRecursion = false;
                        }
                }
 
index e099b38..09314ed 100644 (file)
@@ -32,24 +32,24 @@ use Wikimedia\Rdbms\ILoadBalancer;
  * @author Daniel Kinzler
  */
 abstract class DBAccessBase implements IDBAccessObject {
-       /**
-        * @var string|bool $wiki The target wiki's name. This must be an ID
-        * that LBFactory can understand.
-        */
-       protected $wiki = false;
+       /** @var ILoadBalancer */
+       private $lb;
+
+       /** @var string|bool The target wiki's DB domain */
+       protected $dbDomain = false;
 
        /**
-        * @param string|bool $wiki The target wiki's name. This must be an ID
-        * that LBFactory can understand.
+        * @param string|bool $dbDomain The target wiki's DB domain
         */
-       public function __construct( $wiki = false ) {
-               $this->wiki = $wiki;
+       public function __construct( $dbDomain = false ) {
+               $this->dbDomain = $dbDomain;
+               $this->lb = MediaWikiServices::getInstance()->getDBLoadBalancerFactory()
+                       ->getMainLB( $dbDomain );
        }
 
        /**
         * Returns a database connection.
         *
-        * @see wfGetDB()
         * @see LoadBalancer::getConnection()
         *
         * @since 1.21
@@ -60,9 +60,7 @@ abstract class DBAccessBase implements IDBAccessObject {
         * @return IDatabase
         */
        protected function getConnection( $id, array $groups = [] ) {
-               $loadBalancer = $this->getLoadBalancer();
-
-               return $loadBalancer->getConnection( $id, $groups, $this->wiki );
+               return $this->getLoadBalancer()->getConnectionRef( $id, $groups, $this->dbDomain );
        }
 
        /**
@@ -73,12 +71,10 @@ abstract class DBAccessBase implements IDBAccessObject {
         * @since 1.21
         *
         * @param IDatabase $db The database connection to release.
+        * @deprecated Since 1.34
         */
        protected function releaseConnection( IDatabase $db ) {
-               if ( $this->wiki !== false ) {
-                       $loadBalancer = $this->getLoadBalancer();
-                       $loadBalancer->reuseConnection( $db );
-               }
+               // no-op
        }
 
        /**
@@ -90,8 +86,7 @@ abstract class DBAccessBase implements IDBAccessObject {
         *
         * @return ILoadBalancer The database load balancer object
         */
-       public function getLoadBalancer() {
-               $lbFactory = MediaWikiServices::getInstance()->getDBLoadBalancerFactory();
-               return $lbFactory->getMainLB( $this->wiki );
+       protected function getLoadBalancer() {
+               return $this->lb;
        }
 }
index 5a5e507..a48faf1 100644 (file)
@@ -10,10 +10,16 @@ use Psr\Log\AbstractLogger;
  * goal.
  */
 class ConsoleLogger extends AbstractLogger {
+       /**
+        * @param string $channel
+        */
        public function __construct( $channel ) {
                $this->channel = $channel;
        }
 
+       /**
+        * @inheritDoc
+        */
        public function log( $level, $message, array $context = [] ) {
                fwrite( STDERR, "[$level] " .
                        LegacyLogger::format( $this->channel, $message, $context ) );
index ddffaa3..b983e97 100644 (file)
@@ -24,12 +24,12 @@ use Wikimedia\Assert\Assert;
 use MediaWiki\MediaWikiServices;
 
 /**
- * Handles purging appropriate CDN URLs given a title (or titles)
+ * Handles purging the appropriate CDN objects given a list of URLs or Title instances
  * @ingroup Cache
  */
 class CdnCacheUpdate implements DeferrableUpdate, MergeableUpdate {
        /** @var string[] Collection of URLs to purge */
-       protected $urls = [];
+       private $urls = [];
 
        /**
         * @param string[] $urlArr Collection of URLs to purge
@@ -99,10 +99,9 @@ class CdnCacheUpdate implements DeferrableUpdate, MergeableUpdate {
                wfDebugLog( 'squid', __METHOD__ . ': ' . implode( ' ', $urlArr ) );
 
                // Reliably broadcast the purge to all edge nodes
-               $relayer = MediaWikiServices::getInstance()->getEventRelayerGroup()
-                                       ->getRelayer( 'cdn-url-purges' );
                $ts = microtime( true );
-               $relayer->notifyMulti(
+               $relayerGroup = MediaWikiServices::getInstance()->getEventRelayerGroup();
+               $relayerGroup->getRelayer( 'cdn-url-purges' )->notifyMulti(
                        'cdn-url-purges',
                        array_map(
                                function ( $url ) use ( $ts ) {
@@ -138,7 +137,7 @@ class CdnCacheUpdate implements DeferrableUpdate, MergeableUpdate {
                                foreach ( $chunks as $chunk ) {
                                        $client = new SquidPurgeClient( $server );
                                        foreach ( $chunk as $url ) {
-                                               $client->queuePurge( $url );
+                                               $client->queuePurge( self::expand( $url ) );
                                        }
                                        $pool->addClient( $client );
                                }
@@ -255,7 +254,7 @@ class CdnCacheUpdate implements DeferrableUpdate, MergeableUpdate {
         * @param string $url
         * @return string
         */
-       public static function expand( $url ) {
+       private static function expand( $url ) {
                return wfExpandUrl( $url, PROTO_INTERNAL );
        }
 
index 29846bf..9e45241 100644 (file)
  */
 
 /**
- * Class to invalidate the HTML cache of all the pages linking to a given title.
+ * Class to invalidate the HTML/file cache of all the pages linking to a given title
  *
  * @ingroup Cache
  */
 class HTMLCacheUpdate extends DataUpdate {
        /** @var Title */
-       public $mTitle;
-
+       private $title;
        /** @var string */
-       public $mTable;
+       private $table;
 
        /**
         * @param Title $titleTo
@@ -42,16 +41,16 @@ class HTMLCacheUpdate extends DataUpdate {
        function __construct(
                Title $titleTo, $table, $causeAction = 'unknown', $causeAgent = 'unknown'
        ) {
-               $this->mTitle = $titleTo;
-               $this->mTable = $table;
+               $this->title = $titleTo;
+               $this->table = $table;
                $this->causeAction = $causeAction;
                $this->causeAgent = $causeAgent;
        }
 
        public function doUpdate() {
                $job = HTMLCacheUpdateJob::newForBacklinks(
-                       $this->mTitle,
-                       $this->mTable,
+                       $this->title,
+                       $this->table,
                        [ 'causeAction' => $this->getCauseAction(), 'causeAgent' => $this->getCauseAgent() ]
                );
 
index 74e236f..2bfdc0e 100644 (file)
@@ -125,7 +125,7 @@ class LinksUpdate extends DataUpdate {
 
                if ( !$this->mId ) {
                        // NOTE: subclasses may initialize mId before calling this constructor!
-                       $this->mId = $title->getArticleID( Title::GAID_FOR_UPDATE );
+                       $this->mId = $title->getArticleID( Title::READ_LATEST );
                }
 
                if ( !$this->mId ) {
@@ -1066,6 +1066,7 @@ class LinksUpdate extends DataUpdate {
        private function invalidateProperties( $changed ) {
                global $wgPagePropLinkInvalidations;
 
+               $jobs = [];
                foreach ( $changed as $name => $value ) {
                        if ( isset( $wgPagePropLinkInvalidations[$name] ) ) {
                                $inv = $wgPagePropLinkInvalidations[$name];
@@ -1073,12 +1074,16 @@ class LinksUpdate extends DataUpdate {
                                        $inv = [ $inv ];
                                }
                                foreach ( $inv as $table ) {
-                                       DeferredUpdates::addUpdate(
-                                               new HTMLCacheUpdate( $this->mTitle, $table, 'page-props' )
+                                       $jobs[] = HTMLCacheUpdateJob::newForBacklinks(
+                                               $this->mTitle,
+                                               $table,
+                                               [ 'causeAction' => 'page-props' ]
                                        );
                                }
                        }
                }
+
+               JobQueueGroup::singleton()->lazyPush( $jobs );
        }
 
        /**
@@ -1192,4 +1197,14 @@ class LinksUpdate extends DataUpdate {
 
                return $this->db;
        }
+
+       /**
+        * Whether or not this LinksUpdate will also update pages which transclude the
+        * current page or otherwise depend on it.
+        *
+        * @return bool
+        */
+       public function isRecursive() {
+               return $this->mRecursive;
+       }
 }
index a508746..84f6fc0 100644 (file)
@@ -50,7 +50,7 @@ class SearchUpdate implements DeferrableUpdate {
         */
        public function __construct( $id, $title, $c = null ) {
                if ( is_string( $title ) ) {
-                       wfDeprecated( __METHOD__ . " with a string for the title", 1.34 );
+                       wfDeprecated( __METHOD__ . " with a string for the title", '1.34' );
                        $this->title = Title::newFromText( $title );
                        if ( $this->title === null ) {
                                throw new InvalidArgumentException( "Cannot construct the title: $title" );
@@ -62,10 +62,10 @@ class SearchUpdate implements DeferrableUpdate {
                $this->id = $id;
                // is_string() check is back-compat for ApprovedRevs
                if ( is_string( $c ) ) {
-                       wfDeprecated( __METHOD__ . " with a string for the content", 1.34 );
+                       wfDeprecated( __METHOD__ . " with a string for the content", '1.34' );
                        $c = new TextContent( $c );
                } elseif ( is_bool( $c ) ) {
-                       wfDeprecated( __METHOD__ . " with a boolean for the content", 1.34 );
+                       wfDeprecated( __METHOD__ . " with a boolean for the content", '1.34' );
                        $c = null;
                }
                $this->content = $c;
index 7fcda4c..7e4e53e 100644 (file)
@@ -544,7 +544,7 @@ class DifferenceEngine extends ContextSource {
                        if ( $samePage && $this->mNewPage && $permissionManager->quickUserCan(
                                'edit', $user, $this->mNewPage
                        ) ) {
-                               if ( $this->mNewRev->isCurrent() && $permissionManager->userCan(
+                               if ( $this->mNewRev->isCurrent() && $permissionManager->quickUserCan(
                                        'rollback', $user, $this->mNewPage
                                ) ) {
                                        $rollbackLink = Linker::generateRollback( $this->mNewRev, $this->getContext(),
@@ -1713,14 +1713,29 @@ class DifferenceEngine extends ContextSource {
         *     false signifies that there is no previous/next revision ($old is the oldest/newest one).
         */
        public function mapDiffPrevNext( $old, $new ) {
+               $rl = MediaWikiServices::getInstance()->getRevisionLookup();
                if ( $new === 'prev' ) {
                        // Show diff between revision $old and the previous one. Get previous one from DB.
                        $newid = intval( $old );
-                       $oldid = $this->getTitle()->getPreviousRevisionID( $newid );
+                       $oldid = false;
+                       $newRev = $rl->getRevisionById( $newid );
+                       if ( $newRev ) {
+                               $oldRev = $rl->getPreviousRevision( $newRev );
+                               if ( $oldRev ) {
+                                       $oldid = $oldRev->getId();
+                               }
+                       }
                } elseif ( $new === 'next' ) {
                        // Show diff between revision $old and the next one. Get next one from DB.
                        $oldid = intval( $old );
-                       $newid = $this->getTitle()->getNextRevisionID( $oldid );
+                       $newid = false;
+                       $oldRev = $rl->getRevisionById( $oldid );
+                       if ( $oldRev ) {
+                               $newRev = $rl->getNextRevision( $oldRev );
+                               if ( $newRev ) {
+                                       $newid = $newRev->getId();
+                               }
+                       }
                } else {
                        $oldid = intval( $old );
                        $newid = intval( $new );
index 92118fe..2f5b3dc 100644 (file)
  * @ingroup Dump
  */
 class DumpMultiWriter {
+       /** @var array */
+       private $sinks;
+       /** @var int */
+       private $count;
 
        /**
         * @param array $sinks
index ec0b344..c1b3595 100644 (file)
@@ -30,6 +30,7 @@
 use MediaWiki\MediaWikiServices as MediaWikiServicesAlias;
 use MediaWiki\Storage\RevisionRecord;
 use Wikimedia\Rdbms\IResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
 
 /**
  * @ingroup SpecialPage Dump
@@ -67,7 +68,7 @@ class WikiExporter {
        /** @var XmlDumpWriter */
        private $writer;
 
-       /** @var Database */
+       /** @var IDatabase */
        protected $db;
 
        /** @var array|int */
@@ -86,7 +87,7 @@ class WikiExporter {
        }
 
        /**
-        * @param Database $db
+        * @param IDatabase $db
         * @param int|array $history One of WikiExporter::FULL, WikiExporter::CURRENT,
         *   WikiExporter::RANGE or WikiExporter::STABLE, or an associative array:
         *   - offset: non-inclusive offset at which to start the query
@@ -303,29 +304,36 @@ class WikiExporter {
                if ( $cond ) {
                        $where[] = $cond;
                }
-               # Get logging table name for logging.* clause
-               $logging = $this->db->tableName( 'logging' );
-
                $result = null; // Assuring $result is not undefined, if exception occurs early
 
                $commentQuery = CommentStore::getStore()->getJoin( 'log_comment' );
                $actorQuery = ActorMigration::newMigration()->getJoin( 'log_user' );
 
+               $tables = array_merge(
+                       [ 'logging' ], $commentQuery['tables'], $actorQuery['tables'], [ 'user' ]
+               );
+               $fields = [
+                       'log_id', 'log_type', 'log_action', 'log_timestamp', 'log_namespace',
+                       'log_title', 'log_params', 'log_deleted', 'user_name'
+               ] + $commentQuery['fields'] + $actorQuery['fields'];
+               $options = [
+                       'ORDER BY' => 'log_id',
+                       'USE INDEX' => [ 'logging' => 'PRIMARY' ],
+                       'LIMIT' => self::BATCH_SIZE,
+               ];
+               $joins = [
+                       'user' => [ 'JOIN', 'user_id = ' . $actorQuery['fields']['log_user'] ]
+               ] + $commentQuery['joins'] + $actorQuery['joins'];
+
                $lastLogId = 0;
                while ( true ) {
                        $result = $this->db->select(
-                               array_merge( [ 'logging' ], $commentQuery['tables'], $actorQuery['tables'], [ 'user' ] ),
-                               [ "{$logging}.*", 'user_name' ] + $commentQuery['fields'] + $actorQuery['fields'],
+                               $tables,
+                               $fields,
                                array_merge( $where, [ 'log_id > ' . intval( $lastLogId ) ] ),
                                __METHOD__,
-                               [
-                                       'ORDER BY' => 'log_id',
-                                       'USE INDEX' => [ 'logging' => 'PRIMARY' ],
-                                       'LIMIT' => self::BATCH_SIZE,
-                               ],
-                               [
-                                       'user' => [ 'JOIN', 'user_id = ' . $actorQuery['fields']['log_user'] ]
-                               ] + $commentQuery['joins'] + $actorQuery['joins']
+                               $options,
+                               $joins
                        );
 
                        if ( !$result->numRows() ) {
index 4db351b..264eabc 100644 (file)
@@ -26,6 +26,7 @@ use Wikimedia\Rdbms\IDatabase;
 use Wikimedia\Rdbms\DBConnRef;
 use Wikimedia\Rdbms\MaintainableDBConnRef;
 use Wikimedia\Rdbms\DatabaseDomain;
+use Wikimedia\Rdbms\DBUnexpectedError;
 
 /**
  * DB accessible external objects.
@@ -113,7 +114,11 @@ class ExternalStoreDB extends ExternalStoreMedium {
         */
        public function store( $location, $data ) {
                $dbw = $this->getMaster( $location );
-               $dbw->insert( $this->getTable( $dbw ), [ 'blob_text' => $data ], __METHOD__ );
+               $dbw->insert(
+                       $this->getTable( $dbw, $location ),
+                       [ 'blob_text' => $data ],
+                       __METHOD__
+               );
                $id = $dbw->insertId();
                if ( !$id ) {
                        throw new MWException( __METHOD__ . ': no insert ID' );
@@ -149,10 +154,11 @@ class ExternalStoreDB extends ExternalStoreMedium {
        /**
         * Get a replica DB connection for the specified cluster
         *
+        * @since 1.34
         * @param string $cluster Cluster name
         * @return DBConnRef
         */
-       public function getSlave( $cluster ) {
+       public function getReplica( $cluster ) {
                $lb = $this->getLoadBalancer( $cluster );
 
                return $lb->getConnectionRef(
@@ -163,6 +169,17 @@ class ExternalStoreDB extends ExternalStoreMedium {
                );
        }
 
+       /**
+        * Get a replica DB connection for the specified cluster
+        *
+        * @param string $cluster Cluster name
+        * @return DBConnRef
+        * @deprecated since 1.34
+        */
+       public function getSlave( $cluster ) {
+               return $this->getReplica( $cluster );
+       }
+
        /**
         * Get a master database connection for the specified cluster
         *
@@ -211,15 +228,55 @@ class ExternalStoreDB extends ExternalStoreMedium {
         * Get the 'blobs' table name for this database
         *
         * @param IDatabase $db
+        * @param string|null $cluster Cluster name
         * @return string Table name ('blobs' by default)
         */
-       public function getTable( $db ) {
-               $table = $db->getLBInfo( 'blobs table' );
-               if ( is_null( $table ) ) {
-                       $table = 'blobs';
+       public function getTable( $db, $cluster = null ) {
+               if ( $cluster !== null ) {
+                       $lb = $this->getLoadBalancer( $cluster );
+                       $info = $lb->getServerInfo( $lb->getWriterIndex() );
+                       if ( isset( $info['blobs table'] ) ) {
+                               return $info['blobs table'];
+                       }
                }
 
-               return $table;
+               return $db->getLBInfo( 'blobs table' ) ?? 'blobs'; // b/c
+       }
+
+       /**
+        * Create the appropriate blobs table on this cluster
+        *
+        * @see getTable()
+        * @since 1.34
+        * @param string $cluster
+        */
+       public function initializeTable( $cluster ) {
+               global $IP;
+
+               static $supportedTypes = [ 'mysql', 'sqlite' ];
+
+               $dbw = $this->getMaster( $cluster );
+               if ( !in_array( $dbw->getType(), $supportedTypes, true ) ) {
+                       throw new DBUnexpectedError( $dbw, "RDBMS type '{$dbw->getType()}' not supported." );
+               }
+
+               $sqlFilePath = "$IP/maintenance/storage/blobs.sql";
+               $sql = file_get_contents( $sqlFilePath );
+               if ( $sql === false ) {
+                       throw new RuntimeException( "Failed to read '$sqlFilePath'." );
+               }
+
+               $rawTable = $this->getTable( $dbw, $cluster ); // e.g. "blobs_cluster23"
+               $encTable = $dbw->tableName( $rawTable );
+               $dbw->query(
+                       str_replace(
+                               [ '/*$wgDBprefix*/blobs', '/*_*/blobs' ],
+                               [ $encTable, $encTable ],
+                               $sql
+                       ),
+                       __METHOD__,
+                       $dbw::QUERY_IGNORE_DBO_TRX
+               );
        }
 
        /**
@@ -251,15 +308,23 @@ class ExternalStoreDB extends ExternalStoreMedium {
 
                $this->logger->debug( "ExternalStoreDB::fetchBlob cache miss on $cacheID" );
 
-               $dbr = $this->getSlave( $cluster );
-               $ret = $dbr->selectField( $this->getTable( $dbr ),
-                       'blob_text', [ 'blob_id' => $id ], __METHOD__ );
+               $dbr = $this->getReplica( $cluster );
+               $ret = $dbr->selectField(
+                       $this->getTable( $dbr, $cluster ),
+                       'blob_text',
+                       [ 'blob_id' => $id ],
+                       __METHOD__
+               );
                if ( $ret === false ) {
                        $this->logger->info( "ExternalStoreDB::fetchBlob master fallback on $cacheID" );
                        // Try the master
                        $dbw = $this->getMaster( $cluster );
-                       $ret = $dbw->selectField( $this->getTable( $dbw ),
-                               'blob_text', [ 'blob_id' => $id ], __METHOD__ );
+                       $ret = $dbw->selectField(
+                               $this->getTable( $dbw, $cluster ),
+                               'blob_text',
+                               [ 'blob_id' => $id ],
+                               __METHOD__
+                       );
                        if ( $ret === false ) {
                                $this->logger->error( "ExternalStoreDB::fetchBlob master failed to find $cacheID" );
                        }
@@ -283,9 +348,9 @@ class ExternalStoreDB extends ExternalStoreMedium {
         *   Unlocated ids are not represented
         */
        private function batchFetchBlobs( $cluster, array $ids ) {
-               $dbr = $this->getSlave( $cluster );
+               $dbr = $this->getReplica( $cluster );
                $res = $dbr->select(
-                       $this->getTable( $dbr ),
+                       $this->getTable( $dbr, $cluster ),
                        [ 'blob_id', 'blob_text' ],
                        [ 'blob_id' => array_keys( $ids ) ],
                        __METHOD__
@@ -302,7 +367,8 @@ class ExternalStoreDB extends ExternalStoreMedium {
                        );
                        // Try the master
                        $dbw = $this->getMaster( $cluster );
-                       $res = $dbw->select( $this->getTable( $dbr ),
+                       $res = $dbw->select(
+                               $this->getTable( $dbr, $cluster ),
                                [ 'blob_id', 'blob_text' ],
                                [ 'blob_id' => array_keys( $ids ) ],
                                __METHOD__ );
index 6a3e819..17fa146 100644 (file)
@@ -213,50 +213,6 @@ class ArchivedFile {
                return $file;
        }
 
-       /**
-        * Fields in the filearchive table
-        * @deprecated since 1.31, use self::getQueryInfo() instead.
-        * @return string[]
-        */
-       static function selectFields() {
-               global $wgActorTableSchemaMigrationStage;
-
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->fa_user or $row->fa_user_text and we can't give it
-                       // useful values here once those aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               wfDeprecated( __METHOD__, '1.31' );
-               return [
-                       'fa_id',
-                       'fa_name',
-                       'fa_archive_name',
-                       'fa_storage_key',
-                       'fa_storage_group',
-                       'fa_size',
-                       'fa_bits',
-                       'fa_width',
-                       'fa_height',
-                       'fa_metadata',
-                       'fa_media_type',
-                       'fa_major_mime',
-                       'fa_minor_mime',
-                       'fa_user',
-                       'fa_user_text',
-                       'fa_actor' => 'NULL',
-                       'fa_timestamp',
-                       'fa_deleted',
-                       'fa_deleted_timestamp', /* Used by LocalFileRestoreBatch */
-                       'fa_sha1',
-               ] + MediaWikiServices::getInstance()->getCommentStore()->getFields( 'fa_description' );
-       }
-
        /**
         * Return the tables, fields, and join conditions to be selected to create
         * a new archivedfile object.
index 0d5776b..60d4e29 100644 (file)
@@ -1467,13 +1467,15 @@ abstract class File implements IDBAccessObject {
                // Delete thumbnails and refresh file metadata cache
                $this->purgeCache();
                $this->purgeDescription();
-
                // Purge cache of all pages using this file
                $title = $this->getTitle();
                if ( $title ) {
-                       DeferredUpdates::addUpdate(
-                               new HTMLCacheUpdate( $title, 'imagelinks', 'file-purge' )
+                       $job = HTMLCacheUpdateJob::newForBacklinks(
+                               $title,
+                               'imagelinks',
+                               [ 'causeAction' => 'file-purge' ]
                        );
+                       JobQueueGroup::singleton()->lazyPush( $job );
                }
        }
 
index 3090632..ceb8dda 100644 (file)
@@ -202,44 +202,6 @@ class LocalFile extends File {
                }
        }
 
-       /**
-        * Fields in the image table
-        * @deprecated since 1.31, use self::getQueryInfo() instead.
-        * @return string[]
-        */
-       static function selectFields() {
-               global $wgActorTableSchemaMigrationStage;
-
-               wfDeprecated( __METHOD__, '1.31' );
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->img_user or $row->img_user_text and we can't give it
-                       // useful values here once those aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               return [
-                       'img_name',
-                       'img_size',
-                       'img_width',
-                       'img_height',
-                       'img_metadata',
-                       'img_bits',
-                       'img_media_type',
-                       'img_major_mime',
-                       'img_minor_mime',
-                       'img_user',
-                       'img_user_text',
-                       'img_actor' => 'NULL',
-                       'img_timestamp',
-                       'img_sha1',
-               ] + MediaWikiServices::getInstance()->getCommentStore()->getFields( 'img_description' );
-       }
-
        /**
         * Return the tables, fields, and join conditions to be selected to create
         * a new localfile object.
@@ -1449,8 +1411,6 @@ class LocalFile extends File {
                $oldver, $comment, $pageText, $props = false, $timestamp = false, $user = null, $tags = [],
                $createNullRevision = true, $revert = false
        ) {
-               global $wgActorTableSchemaMigrationStage;
-
                if ( is_null( $user ) ) {
                        global $wgUser;
                        $user = $wgUser;
@@ -1553,40 +1513,10 @@ class LocalFile extends File {
                                'oi_major_mime' => 'img_major_mime',
                                'oi_minor_mime' => 'img_minor_mime',
                                'oi_sha1' => 'img_sha1',
+                               'oi_actor' => 'img_actor',
                        ];
                        $joins = [];
 
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
-                               $fields['oi_user'] = 'img_user';
-                               $fields['oi_user_text'] = 'img_user_text';
-                       }
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                               $fields['oi_actor'] = 'img_actor';
-                       }
-
-                       if (
-                               ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_BOTH ) === SCHEMA_COMPAT_WRITE_BOTH
-                       ) {
-                               // Upgrade any rows that are still old-style. Otherwise an upgrade
-                               // might be missed if a deletion happens while the migration script
-                               // is running.
-                               $res = $dbw->select(
-                                       [ 'image' ],
-                                       [ 'img_name', 'img_user', 'img_user_text' ],
-                                       [ 'img_name' => $this->getName(), 'img_actor' => 0 ],
-                                       __METHOD__
-                               );
-                               foreach ( $res as $row ) {
-                                       $actorId = User::newFromAnyId( $row->img_user, $row->img_user_text, null )->getActorId( $dbw );
-                                       $dbw->update(
-                                               'image',
-                                               [ 'img_actor' => $actorId ],
-                                               [ 'img_name' => $row->img_name, 'img_actor' => 0 ],
-                                               __METHOD__
-                                       );
-                               }
-                       }
-
                        # (T36993) Note: $oldver can be empty here, if the previous
                        # version of the file was broken. Allow registration of the new
                        # version to continue anyway, because that's better than having
index 61faa09..85988f6 100644 (file)
@@ -178,8 +178,6 @@ class LocalFileDeleteBatch {
        }
 
        protected function doDBInserts() {
-               global $wgActorTableSchemaMigrationStage;
-
                $now = time();
                $dbw = $this->file->repo->getMasterDB();
 
@@ -225,7 +223,8 @@ class LocalFileDeleteBatch {
                                'fa_minor_mime' => 'img_minor_mime',
                                'fa_description_id' => 'img_description_id',
                                'fa_timestamp' => 'img_timestamp',
-                               'fa_sha1' => 'img_sha1'
+                               'fa_sha1' => 'img_sha1',
+                               'fa_actor' => 'img_actor',
                        ];
                        $joins = [];
 
@@ -234,37 +233,6 @@ class LocalFileDeleteBatch {
                                $commentStore->insert( $dbw, 'fa_deleted_reason', $this->reason )
                        );
 
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
-                               $fields['fa_user'] = 'img_user';
-                               $fields['fa_user_text'] = 'img_user_text';
-                       }
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                               $fields['fa_actor'] = 'img_actor';
-                       }
-
-                       if (
-                               ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_BOTH ) === SCHEMA_COMPAT_WRITE_BOTH
-                       ) {
-                               // Upgrade any rows that are still old-style. Otherwise an upgrade
-                               // might be missed if a deletion happens while the migration script
-                               // is running.
-                               $res = $dbw->select(
-                                       [ 'image' ],
-                                       [ 'img_name', 'img_user', 'img_user_text' ],
-                                       [ 'img_name' => $this->file->getName(), 'img_actor' => 0 ],
-                                       __METHOD__
-                               );
-                               foreach ( $res as $row ) {
-                                       $actorId = User::newFromAnyId( $row->img_user, $row->img_user_text, null )->getActorId( $dbw );
-                                       $dbw->update(
-                                               'image',
-                                               [ 'img_actor' => $actorId ],
-                                               [ 'img_name' => $row->img_name, 'img_actor' => 0 ],
-                                               __METHOD__
-                                       );
-                               }
-                       }
-
                        $dbw->insertSelect( 'filearchive', $tables, $fields,
                                [ 'img_name' => $this->file->getName() ], __METHOD__, [], [], $joins );
                }
index 21980b9..0cdc2d5 100644 (file)
@@ -46,6 +46,24 @@ class LocalFileMoveBatch {
        /** @var IDatabase */
        protected $db;
 
+       /** @var string */
+       protected $oldHash;
+
+       /** @var string */
+       protected $newHash;
+
+       /** @var string */
+       protected $oldName;
+
+       /** @var string */
+       protected $newName;
+
+       /** @var string */
+       protected $oldRel;
+
+       /** @var string */
+       protected $newRel;
+
        /**
         * @param File $file
         * @param Title $target
index 584e001..f5b7d43 100644 (file)
@@ -106,46 +106,6 @@ class OldLocalFile extends LocalFile {
                }
        }
 
-       /**
-        * Fields in the oldimage table
-        * @deprecated since 1.31, use self::getQueryInfo() instead.
-        * @return string[]
-        */
-       static function selectFields() {
-               global $wgActorTableSchemaMigrationStage;
-
-               wfDeprecated( __METHOD__, '1.31' );
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                       // If code is using this instead of self::getQueryInfo(), there's a
-                       // decent chance it's going to try to directly access
-                       // $row->oi_user or $row->oi_user_text and we can't give it
-                       // useful values here once those aren't being used anymore.
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage has SCHEMA_COMPAT_READ_NEW'
-                       );
-               }
-
-               return [
-                       'oi_name',
-                       'oi_archive_name',
-                       'oi_size',
-                       'oi_width',
-                       'oi_height',
-                       'oi_metadata',
-                       'oi_bits',
-                       'oi_media_type',
-                       'oi_major_mime',
-                       'oi_minor_mime',
-                       'oi_user',
-                       'oi_user_text',
-                       'oi_actor' => 'NULL',
-                       'oi_timestamp',
-                       'oi_deleted',
-                       'oi_sha1',
-               ] + MediaWikiServices::getInstance()->getCommentStore()->getFields( 'oi_description' );
-       }
-
        /**
         * Return the tables, fields, and join conditions to be selected to create
         * a new oldlocalfile object.
index c6d8ddf..4781a48 100644 (file)
@@ -88,6 +88,15 @@ abstract class ImageGalleryBase extends ContextSource {
        /** @var array */
        protected $mAttribs = [];
 
+       /** @var int */
+       protected $mPerRow;
+
+       /** @var int */
+       protected $mWidths;
+
+       /** @var int */
+       protected $mHeights;
+
        /** @var array */
        private static $modeMapping;
 
index e6936cb..2f8f5dd 100644 (file)
@@ -30,6 +30,9 @@ use MediaWiki\MediaWikiServices;
  * @ingroup SpecialPage
  */
 class ImportStreamSource implements ImportSource {
+       /**
+        * @param resource $handle
+        */
        function __construct( $handle ) {
                $this->mHandle = $handle;
        }
index 85983b1..b75ea1a 100644 (file)
  * @ingroup SpecialPage
  */
 class ImportStringSource implements ImportSource {
+       /** @var string */
+       private $mString;
+
+       /** @var bool */
+       private $mRead;
+
+       /**
+        * @param string $string
+        */
        function __construct( $string ) {
                $this->mString = $string;
                $this->mRead = false;
index 424c9d7..0ff34b0 100644 (file)
@@ -120,7 +120,11 @@ class CliInstaller extends Installer {
                        }
                        $this->setVar( '_Extensions', $status->value );
                } elseif ( isset( $options['with-extensions'] ) ) {
-                       $this->setVar( '_Extensions', array_keys( $this->findExtensions() ) );
+                       $status = $this->findExtensions();
+                       if ( !$status->isOK() ) {
+                               throw new InstallException( $status );
+                       }
+                       $this->setVar( '_Extensions', array_keys( $status->value ) );
                }
 
                // Set up the default skins
@@ -131,7 +135,11 @@ class CliInstaller extends Installer {
                        }
                        $skins = $status->value;
                } else {
-                       $skins = array_keys( $this->findExtensions( 'skins' ) );
+                       $status = $this->findExtensions( 'skins' );
+                       if ( !$status->isOK() ) {
+                               throw new InstallException( $status );
+                       }
+                       $skins = array_keys( $status->value );
                }
                $this->setVar( '_Skins', $skins );
 
index e1df844..3412aef 100644 (file)
@@ -1308,10 +1308,7 @@ abstract class DatabaseUpdater {
         * @since 1.31
         */
        protected function migrateActors() {
-               global $wgActorTableSchemaMigrationStage;
-               if ( ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) &&
-                       !$this->updateRowExists( 'MigrateActors' )
-               ) {
+               if ( !$this->updateRowExists( 'MigrateActors' ) ) {
                        $this->output(
                                "Migrating actors to the 'actor' table, printing progress markers. For large\n" .
                                "databases, you may want to hit Ctrl-C and do this manually with\n" .
@@ -1401,4 +1398,43 @@ abstract class DatabaseUpdater {
                        }
                }
        }
+
+       /**
+        * Only run a function if the `actor` table does not exist
+        *
+        * The transition to the actor table is dropping several indexes (and a few
+        * fields) that old upgrades want to add. This function is used to prevent
+        * those from running to re-add things when the `actor` table exists, while
+        * still allowing them to run if this really is an upgrade from an old MW
+        * version.
+        *
+        * @since 1.34
+        * @param string|array|static $func Normally this is the string naming the method on $this to
+        *  call. It may also be an array callable. If passed $this, it's assumed to be a call from
+        *  runUpdates() with $passSelf = true: $params[0] is assumed to be the real $func and $this
+        *  is prepended to the rest of $params.
+        * @param mixed ...$params Parameters for `$func`
+        * @return mixed Whatever $func returns, or null when skipped.
+        */
+       protected function ifNoActorTable( $func, ...$params ) {
+               if ( $this->tableExists( 'actor' ) ) {
+                       return null;
+               }
+
+               // Handle $passSelf from runUpdates().
+               $passSelf = false;
+               if ( $func === $this ) {
+                       $passSelf = true;
+                       $func = array_shift( $params );
+               }
+
+               if ( !is_array( $func ) && method_exists( $this, $func ) ) {
+                       $func = [ $this, $func ];
+               } elseif ( $passSelf ) {
+                       array_unshift( $params, $this );
+               }
+
+               // @phan-suppress-next-line PhanUndeclaredInvokeInCallable Phan is confused
+               return $func( ...$params );
+       }
 }
index 6d1e211..b830b70 100644 (file)
@@ -1273,7 +1273,8 @@ abstract class Installer {
         *
         * @param string $directory Directory to search in, relative to $IP, must be either "extensions"
         *     or "skins"
-        * @return array[][] [ $extName => [ 'screenshots' => [ '...' ] ]
+        * @return Status An object containing an error list. If there were no errors, an associative
+        *     array of information about the extension can be found in $status->value.
         */
        public function findExtensions( $directory = 'extensions' ) {
                switch ( $directory ) {
@@ -1292,33 +1293,43 @@ abstract class Installer {
         *
         * @param string $type Either "extension" or "skin"
         * @param string $directory Directory to search in, relative to $IP
-        * @return array [ $extName => [ 'screenshots' => [ '...' ] ]
+        * @return Status An object containing an error list. If there were no errors, an associative
+        *     array of information about the extension can be found in $status->value.
         */
        protected function findExtensionsByType( $type = 'extension', $directory = 'extensions' ) {
                if ( $this->getVar( 'IP' ) === null ) {
-                       return [];
+                       return Status::newGood( [] );
                }
 
                $extDir = $this->getVar( 'IP' ) . '/' . $directory;
                if ( !is_readable( $extDir ) || !is_dir( $extDir ) ) {
-                       return [];
+                       return Status::newGood( [] );
                }
 
                $dh = opendir( $extDir );
                $exts = [];
+               $status = new Status;
                while ( ( $file = readdir( $dh ) ) !== false ) {
-                       if ( !is_dir( "$extDir/$file" ) ) {
+                       // skip non-dirs and hidden directories
+                       if ( !is_dir( "$extDir/$file" ) || $file[0] === '.' ) {
                                continue;
                        }
-                       $status = $this->getExtensionInfo( $type, $directory, $file );
-                       if ( $status->isOK() ) {
-                               $exts[$file] = $status->value;
+                       $extStatus = $this->getExtensionInfo( $type, $directory, $file );
+                       if ( $extStatus->isOK() ) {
+                               $exts[$file] = $extStatus->value;
+                       } elseif ( $extStatus->hasMessage( 'config-extension-not-found' ) ) {
+                               // (T225512) The directory is not actually an extension. Downgrade to warning.
+                               $status->warning( 'config-extension-not-found', $file );
+                       } else {
+                               $status->merge( $extStatus );
                        }
                }
                closedir( $dh );
                uksort( $exts, 'strnatcasecmp' );
 
-               return $exts;
+               $status->value = $exts;
+
+               return $status;
        }
 
        /**
@@ -1419,11 +1430,16 @@ abstract class Installer {
                        } elseif ( $e->missingExtensions || $e->missingSkins ) {
                                // There's an extension missing in the dependency tree,
                                // so add those to the dependency list and try again
-                               return $this->readExtension(
+                               $status = $this->readExtension(
                                        $fullJsonFile,
                                        array_merge( $extDeps, $e->missingExtensions ),
                                        array_merge( $skinDeps, $e->missingSkins )
                                );
+                               if ( !$status->isOK() && !$status->hasMessage( 'config-extension-dependency' ) ) {
+                                       $status = Status::newFatal( 'config-extension-dependency',
+                                               basename( dirname( $fullJsonFile ) ), $status->getMessage() );
+                               }
+                               return $status;
                        }
                        // Some other kind of dependency error?
                        return Status::newFatal( 'config-extension-dependency',
index 0d516b4..64c017b 100644 (file)
@@ -101,8 +101,10 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'addTable', 'querycache_info', 'patch-querycacheinfo.sql' ],
                        [ 'addTable', 'filearchive', 'patch-filearchive.sql' ],
                        [ 'addField', 'ipblocks', 'ipb_anon_only', 'patch-ipb_anon_only.sql' ],
-                       [ 'addIndex', 'recentchanges', 'rc_ns_usertext', 'patch-recentchanges-utindex.sql' ],
-                       [ 'addIndex', 'recentchanges', 'rc_user_text', 'patch-rc_user_text-index.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'recentchanges', 'rc_ns_usertext',
+                               'patch-recentchanges-utindex.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'recentchanges', 'rc_user_text',
+                               'patch-rc_user_text-index.sql' ],
 
                        // 1.9
                        [ 'addField', 'user', 'user_newpass_time', 'patch-user_newpass_time.sql' ],
@@ -130,9 +132,12 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'addField', 'ipblocks', 'ipb_block_email', 'patch-ipb_emailban.sql' ],
                        [ 'doCategorylinksIndicesUpdate' ],
                        [ 'addField', 'oldimage', 'oi_metadata', 'patch-oi_metadata.sql' ],
-                       [ 'addIndex', 'archive', 'usertext_timestamp', 'patch-archive-user-index.sql' ],
-                       [ 'addIndex', 'image', 'img_usertext_timestamp', 'patch-image-user-index.sql' ],
-                       [ 'addIndex', 'oldimage', 'oi_usertext_timestamp', 'patch-oldimage-user-index.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'archive', 'usertext_timestamp',
+                               'patch-archive-user-index.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'image', 'img_usertext_timestamp',
+                               'patch-image-user-index.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'oldimage', 'oi_usertext_timestamp',
+                               'patch-oldimage-user-index.sql' ],
                        [ 'addField', 'archive', 'ar_page_id', 'patch-archive-page_id.sql' ],
                        [ 'addField', 'image', 'img_sha1', 'patch-img_sha1.sql' ],
 
@@ -140,7 +145,7 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'addTable', 'protected_titles', 'patch-protected_titles.sql' ],
 
                        // 1.13
-                       [ 'addField', 'ipblocks', 'ipb_by_text', 'patch-ipb_by_text.sql' ],
+                       [ 'ifNoActorTable', 'addField', 'ipblocks', 'ipb_by_text', 'patch-ipb_by_text.sql' ],
                        [ 'addTable', 'page_props', 'patch-page_props.sql' ],
                        [ 'addTable', 'updatelog', 'patch-updatelog.sql' ],
                        [ 'addTable', 'category', 'patch-category.sql' ],
@@ -150,7 +155,7 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'doPopulateParentId' ],
                        [ 'checkBin', 'protected_titles', 'pt_title', 'patch-pt_title-encoding.sql', ],
                        [ 'doMaybeProfilingMemoryUpdate' ],
-                       [ 'doFilearchiveIndicesUpdate' ],
+                       [ 'ifNoActorTable', 'doFilearchiveIndicesUpdate' ],
 
                        // 1.14
                        [ 'addField', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ],
@@ -163,9 +168,9 @@ class MysqlUpdater extends DatabaseUpdater {
                        // 1.16
                        [ 'addTable', 'user_properties', 'patch-user_properties.sql' ],
                        [ 'addTable', 'log_search', 'patch-log_search.sql' ],
-                       [ 'addField', 'logging', 'log_user_text', 'patch-log_user_text.sql' ],
+                       [ 'ifNoActorTable', 'addField', 'logging', 'log_user_text', 'patch-log_user_text.sql' ],
                        # listed separately from the previous update because 1.16 was released without this update
-                       [ 'doLogUsertextPopulation' ],
+                       [ 'ifNoActorTable', 'doLogUsertextPopulation' ],
                        [ 'doLogSearchPopulation' ],
                        [ 'addTable', 'l10n_cache', 'patch-l10n_cache.sql' ],
                        [ 'dropIndex', 'change_tag', 'ct_rc_id', 'patch-change_tag-indexes.sql' ],
@@ -240,9 +245,10 @@ class MysqlUpdater extends DatabaseUpdater {
 
                        // 1.23
                        [ 'addField', 'recentchanges', 'rc_source', 'patch-rc_source.sql' ],
-                       [ 'addIndex', 'logging', 'log_user_text_type_time',
+                       [ 'ifNoActorTable', 'addIndex', 'logging', 'log_user_text_type_time',
                                'patch-logging_user_text_type_time_index.sql' ],
-                       [ 'addIndex', 'logging', 'log_user_text_time', 'patch-logging_user_text_time_index.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'logging', 'log_user_text_time',
+                               'patch-logging_user_text_time_index.sql' ],
                        [ 'addField', 'page', 'page_links_updated', 'patch-page_links_updated.sql' ],
                        [ 'addField', 'user', 'user_password_expires', 'patch-user_password_expire.sql' ],
 
@@ -288,13 +294,14 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'doNonUniquePlTlIl' ],
                        [ 'addField', 'change_tag', 'ct_id', 'patch-change_tag-ct_id.sql' ],
                        [ 'modifyField', 'recentchanges', 'rc_ip', 'patch-rc_ip_modify.sql' ],
-                       [ 'addIndex', 'archive', 'usertext_timestamp', 'patch-rename-ar_usertext_timestamp.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'archive', 'usertext_timestamp',
+                               'patch-rename-ar_usertext_timestamp.sql' ],
 
                        // 1.29
                        [ 'addField', 'externallinks', 'el_index_60', 'patch-externallinks-el_index_60.sql' ],
                        [ 'dropIndex', 'user_groups', 'ug_user_group', 'patch-user_groups-primary-key.sql' ],
                        [ 'addField', 'user_groups', 'ug_expiry', 'patch-user_groups-ug_expiry.sql' ],
-                       [ 'addIndex', 'image', 'img_user_timestamp', 'patch-image-user-index-2.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'image', 'img_user_timestamp', 'patch-image-user-index-2.sql' ],
 
                        // 1.30
                        [ 'modifyField', 'image', 'img_media_type', 'patch-add-3d.sql' ],
@@ -377,6 +384,9 @@ class MysqlUpdater extends DatabaseUpdater {
                        [ 'dropTable', 'tag_summary' ],
                        [ 'dropField', 'protected_titles', 'pt_reason', 'patch-drop-comment-fields.sql' ],
                        [ 'modifyTable', 'job', 'patch-job-params-mediumblob.sql' ],
+
+                       // 1.34
+                       [ 'dropField', 'logging', 'log_user', 'patch-drop-user-fields.sql' ],
                ];
        }
 
index 31827a1..b2c7d66 100644 (file)
@@ -110,7 +110,7 @@ class PostgresUpdater extends DatabaseUpdater {
                        [ 'addPgField', 'image', 'img_sha1', "TEXT NOT NULL DEFAULT ''" ],
                        [ 'addPgField', 'ipblocks', 'ipb_allow_usertalk', 'SMALLINT NOT NULL DEFAULT 0' ],
                        [ 'addPgField', 'ipblocks', 'ipb_anon_only', 'SMALLINT NOT NULL DEFAULT 0' ],
-                       [ 'addPgField', 'ipblocks', 'ipb_by_text', "TEXT NOT NULL DEFAULT ''" ],
+                       [ 'ifNoActorTable', 'addPgField', 'ipblocks', 'ipb_by_text', "TEXT NOT NULL DEFAULT ''" ],
                        [ 'addPgField', 'ipblocks', 'ipb_block_email', 'SMALLINT NOT NULL DEFAULT 0' ],
                        [ 'addPgField', 'ipblocks', 'ipb_create_account', 'SMALLINT NOT NULL DEFAULT 1' ],
                        [ 'addPgField', 'ipblocks', 'ipb_deleted', 'SMALLINT NOT NULL DEFAULT 0' ],
@@ -152,7 +152,7 @@ class PostgresUpdater extends DatabaseUpdater {
                        [ 'addPgField', 'revision', 'rev_content_format', 'TEXT' ],
                        [ 'addPgField', 'site_stats', 'ss_active_users', "INTEGER DEFAULT '-1'" ],
                        [ 'addPgField', 'user_newtalk', 'user_last_timestamp', 'TIMESTAMPTZ' ],
-                       [ 'addPgField', 'logging', 'log_user_text', "TEXT NOT NULL DEFAULT ''" ],
+                       [ 'ifNoActorTable', 'addPgField', 'logging', 'log_user_text', "TEXT NOT NULL DEFAULT ''" ],
                        [ 'addPgField', 'logging', 'log_page', 'INTEGER' ],
                        [ 'addPgField', 'interwiki', 'iw_api', "TEXT NOT NULL DEFAULT ''" ],
                        [ 'addPgField', 'interwiki', 'iw_wikiid', "TEXT NOT NULL DEFAULT ''" ],
@@ -240,7 +240,7 @@ class PostgresUpdater extends DatabaseUpdater {
                        [ 'checkOiDeleted' ],
 
                        # New indexes
-                       [ 'addPgIndex', 'archive', 'archive_user_text', '(ar_user_text)' ],
+                       [ 'ifNoActorTable', 'addPgIndex', 'archive', 'archive_user_text', '(ar_user_text)' ],
                        [ 'addPgIndex', 'image', 'img_sha1', '(img_sha1)' ],
                        [ 'addPgIndex', 'ipblocks', 'ipb_parent_block_id', '(ipb_parent_block_id)' ],
                        [ 'addPgIndex', 'oldimage', 'oi_sha1', '(oi_sha1)' ],
@@ -253,7 +253,7 @@ class PostgresUpdater extends DatabaseUpdater {
                        [ 'addPgIndex', 'watchlist', 'wl_user', '(wl_user)' ],
                        [ 'addPgIndex', 'watchlist', 'wl_user_notificationtimestamp',
                                '(wl_user, wl_notificationtimestamp)' ],
-                       [ 'addPgIndex', 'logging', 'logging_user_type_time',
+                       [ 'ifNoActorTable', 'addPgIndex', 'logging', 'logging_user_type_time',
                                '(log_user, log_type, log_timestamp)' ],
                        [ 'addPgIndex', 'logging', 'logging_page_id_time', '(log_page,log_timestamp)' ],
                        [ 'addPgIndex', 'iwlinks', 'iwl_prefix_from_title', '(iwl_prefix, iwl_from, iwl_title)' ],
@@ -263,9 +263,10 @@ class PostgresUpdater extends DatabaseUpdater {
                        [ 'addPgIndex', 'job', 'job_cmd_token', '(job_cmd, job_token, job_random)' ],
                        [ 'addPgIndex', 'job', 'job_cmd_token_id', '(job_cmd, job_token, job_id)' ],
                        [ 'addPgIndex', 'filearchive', 'fa_sha1', '(fa_sha1)' ],
-                       [ 'addPgIndex', 'logging', 'logging_user_text_type_time',
+                       [ 'ifNoActorTable', 'addPgIndex', 'logging', 'logging_user_text_type_time',
                                '(log_user_text, log_type, log_timestamp)' ],
-                       [ 'addPgIndex', 'logging', 'logging_user_text_time', '(log_user_text, log_timestamp)' ],
+                       [ 'ifNoActorTable', 'addPgIndex', 'logging', 'logging_user_text_time',
+                               '(log_user_text, log_timestamp)' ],
 
                        [ 'checkIndex', 'pagelink_unique', [
                                [ 'pl_from', 'int4_ops', 'btree', 0 ],
@@ -363,30 +364,36 @@ class PostgresUpdater extends DatabaseUpdater {
                        [ 'checkIwlPrefix' ],
 
                        # All FK columns should be deferred
-                       [ 'changeFkeyDeferrable', 'archive', 'ar_user', 'mwuser(user_id) ON DELETE SET NULL' ],
+                       [ 'ifNoActorTable', 'changeFkeyDeferrable', 'archive', 'ar_user',
+                               'mwuser(user_id) ON DELETE SET NULL' ],
                        [ 'changeFkeyDeferrable', 'categorylinks', 'cl_from', 'page(page_id) ON DELETE CASCADE' ],
                        [ 'changeFkeyDeferrable', 'externallinks', 'el_from', 'page(page_id) ON DELETE CASCADE' ],
                        [ 'changeFkeyDeferrable', 'filearchive', 'fa_deleted_user',
                                'mwuser(user_id) ON DELETE SET NULL' ],
-                       [ 'changeFkeyDeferrable', 'filearchive', 'fa_user', 'mwuser(user_id) ON DELETE SET NULL' ],
-                       [ 'changeFkeyDeferrable', 'image', 'img_user', 'mwuser(user_id) ON DELETE SET NULL' ],
+                       [ 'ifNoActorTable', 'changeFkeyDeferrable', 'filearchive', 'fa_user',
+                               'mwuser(user_id) ON DELETE SET NULL' ],
+                       [ 'ifNoActorTable', 'changeFkeyDeferrable', 'image', 'img_user',
+                               'mwuser(user_id) ON DELETE SET NULL' ],
                        [ 'changeFkeyDeferrable', 'imagelinks', 'il_from', 'page(page_id) ON DELETE CASCADE' ],
-                       [ 'changeFkeyDeferrable', 'ipblocks', 'ipb_by', 'mwuser(user_id) ON DELETE CASCADE' ],
+                       [ 'ifNoActorTable', 'changeFkeyDeferrable', 'ipblocks', 'ipb_by',
+                               'mwuser(user_id) ON DELETE CASCADE' ],
                        [ 'changeFkeyDeferrable', 'ipblocks', 'ipb_user', 'mwuser(user_id) ON DELETE SET NULL' ],
                        [ 'changeFkeyDeferrable', 'ipblocks', 'ipb_parent_block_id',
                                'ipblocks(ipb_id) ON DELETE SET NULL' ],
                        [ 'changeFkeyDeferrable', 'langlinks', 'll_from', 'page(page_id) ON DELETE CASCADE' ],
-                       [ 'changeFkeyDeferrable', 'logging', 'log_user', 'mwuser(user_id) ON DELETE SET NULL' ],
+                       [ 'ifNoActorTable', 'changeFkeyDeferrable', 'logging', 'log_user',
+                               'mwuser(user_id) ON DELETE SET NULL' ],
                        [ 'changeFkeyDeferrable', 'oldimage', 'oi_name',
                                'image(img_name) ON DELETE CASCADE ON UPDATE CASCADE' ],
-                       [ 'changeFkeyDeferrable', 'oldimage', 'oi_user', 'mwuser(user_id) ON DELETE SET NULL' ],
+                       [ 'ifNoActorTable', 'changeFkeyDeferrable', 'oldimage', 'oi_user',
+                               'mwuser(user_id) ON DELETE SET NULL' ],
                        [ 'changeFkeyDeferrable', 'pagelinks', 'pl_from', 'page(page_id) ON DELETE CASCADE' ],
                        [ 'changeFkeyDeferrable', 'page_props', 'pp_page', 'page (page_id) ON DELETE CASCADE' ],
                        [ 'changeFkeyDeferrable', 'page_restrictions', 'pr_page',
                                'page(page_id) ON DELETE CASCADE' ],
                        [ 'changeFkeyDeferrable', 'protected_titles', 'pt_user',
                                'mwuser(user_id) ON DELETE SET NULL' ],
-                       [ 'changeFkeyDeferrable', 'recentchanges', 'rc_user',
+                       [ 'ifNoActorTable', 'changeFkeyDeferrable', 'recentchanges', 'rc_user',
                                'mwuser(user_id) ON DELETE SET NULL' ],
                        [ 'changeFkeyDeferrable', 'redirect', 'rd_from', 'page(page_id) ON DELETE CASCADE' ],
                        [ 'changeFkeyDeferrable', 'revision', 'rev_page', 'page (page_id) ON DELETE CASCADE' ],
@@ -618,6 +625,34 @@ class PostgresUpdater extends DatabaseUpdater {
                        [ 'dropDefault', 'logging', 'log_comment_id' ],
                        [ 'dropPgField', 'protected_titles', 'pt_reason' ],
                        [ 'dropDefault', 'protected_titles', 'pt_reason_id' ],
+
+                       // 1.34
+                       [ 'dropPgIndex', 'archive', 'archive_user_text' ],
+                       [ 'dropPgField', 'archive', 'ar_user' ],
+                       [ 'dropPgField', 'archive', 'ar_user_text' ],
+                       [ 'dropDefault', 'archive', 'ar_actor' ],
+                       [ 'dropPgField', 'ipblocks', 'ipb_by' ],
+                       [ 'dropPgField', 'ipblocks', 'ipb_by_text' ],
+                       [ 'dropDefault', 'ipblocks', 'ipb_by_actor' ],
+                       [ 'dropPgField', 'image', 'img_user' ],
+                       [ 'dropPgField', 'image', 'img_user_text' ],
+                       [ 'dropDefault', 'image', 'img_actor' ],
+                       [ 'dropPgField', 'oldimage', 'oi_user' ],
+                       [ 'dropPgField', 'oldimage', 'oi_user_text' ],
+                       [ 'dropDefault', 'oldimage', 'oi_actor' ],
+                       [ 'dropPgField', 'filearchive', 'fa_user' ],
+                       [ 'dropPgField', 'filearchive', 'fa_user_text' ],
+                       [ 'dropDefault', 'filearchive', 'fa_actor' ],
+                       [ 'dropPgField', 'recentchanges', 'rc_user' ],
+                       [ 'dropPgField', 'recentchanges', 'rc_user_text' ],
+                       [ 'dropDefault', 'recentchanges', 'rc_actor' ],
+                       [ 'dropPgIndex', 'logging', 'logging_user_time' ],
+                       [ 'dropPgIndex', 'logging', 'logging_user_type_time' ],
+                       [ 'dropPgIndex', 'logging', 'logging_user_text_type_time' ],
+                       [ 'dropPgIndex', 'logging', 'logging_user_text_time' ],
+                       [ 'dropPgField', 'logging', 'log_user' ],
+                       [ 'dropPgField', 'logging', 'log_user_text' ],
+                       [ 'dropDefault', 'logging', 'log_actor' ],
                ];
        }
 
index 17ced50..7c3878c 100644 (file)
@@ -47,9 +47,9 @@ class SqliteUpdater extends DatabaseUpdater {
                        // 1.16
                        [ 'addTable', 'user_properties', 'patch-user_properties.sql' ],
                        [ 'addTable', 'log_search', 'patch-log_search.sql' ],
-                       [ 'addField', 'logging', 'log_user_text', 'patch-log_user_text.sql' ],
+                       [ 'ifNoActorTable', 'addField', 'logging', 'log_user_text', 'patch-log_user_text.sql' ],
                        # listed separately from the previous update because 1.16 was released without this update
-                       [ 'doLogUsertextPopulation' ],
+                       [ 'ifNoActorTable', 'doLogUsertextPopulation' ],
                        [ 'doLogSearchPopulation' ],
                        [ 'addTable', 'l10n_cache', 'patch-l10n_cache.sql' ],
                        [ 'dropIndex', 'change_tag', 'ct_rc_id', 'patch-change_tag-indexes.sql' ],
@@ -119,9 +119,10 @@ class SqliteUpdater extends DatabaseUpdater {
 
                        // 1.23
                        [ 'addField', 'recentchanges', 'rc_source', 'patch-rc_source.sql' ],
-                       [ 'addIndex', 'logging', 'log_user_text_type_time',
+                       [ 'ifNoActorTable', 'addIndex', 'logging', 'log_user_text_type_time',
                                'patch-logging_user_text_type_time_index.sql' ],
-                       [ 'addIndex', 'logging', 'log_user_text_time', 'patch-logging_user_text_time_index.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'logging', 'log_user_text_time',
+                               'patch-logging_user_text_time_index.sql' ],
                        [ 'addField', 'page', 'page_links_updated', 'patch-page_links_updated.sql' ],
                        [ 'addField', 'user', 'user_password_expires', 'patch-user_password_expire.sql' ],
 
@@ -159,7 +160,7 @@ class SqliteUpdater extends DatabaseUpdater {
                        // 1.29
                        [ 'addField', 'externallinks', 'el_index_60', 'patch-externallinks-el_index_60.sql' ],
                        [ 'addField', 'user_groups', 'ug_expiry', 'patch-user_groups-ug_expiry.sql' ],
-                       [ 'addIndex', 'image', 'img_user_timestamp', 'patch-image-user-index-2.sql' ],
+                       [ 'ifNoActorTable', 'addIndex', 'image', 'img_user_timestamp', 'patch-image-user-index-2.sql' ],
 
                        // 1.30
                        [ 'modifyField', 'image', 'img_media_type', 'patch-add-3d.sql' ],
@@ -249,6 +250,15 @@ class SqliteUpdater extends DatabaseUpdater {
                        [ 'dropField', 'recentchanges', 'rc_comment', 'patch-recentchanges-drop-rc_comment.sql' ],
                        [ 'dropField', 'logging', 'log_comment', 'patch-logging-drop-log_comment.sql' ],
                        [ 'dropField', 'protected_titles', 'pt_reason', 'patch-protected_titles-drop-pt_reason.sql' ],
+
+                       // 1.34
+                       [ 'dropField', 'archive', 'ar_user', 'patch-archive-drop-ar_user.sql' ],
+                       [ 'dropField', 'ipblocks', 'ipb_by', 'patch-ipblocks-drop-ipb_by.sql' ],
+                       [ 'dropField', 'image', 'img_user', 'patch-image-drop-img_user.sql' ],
+                       [ 'dropField', 'oldimage', 'oi_user', 'patch-oldimage-drop-oi_user.sql' ],
+                       [ 'dropField', 'filearchive', 'fa_user', 'patch-filearchive-drop-fa_user.sql' ],
+                       [ 'dropField', 'recentchanges', 'rc_user', 'patch-recentchanges-drop-rc_user.sql' ],
+                       [ 'dropField', 'logging', 'log_user', 'patch-logging-drop-log_user.sql' ],
                ];
        }
 
index 2412319..7bec49a 100644 (file)
@@ -104,7 +104,8 @@ class WebInstallerOptions extends WebInstallerPage {
                        $this->getFieldsetEnd()
                );
 
-               $skins = $this->parent->findExtensions( 'skins' );
+               $skins = $this->parent->findExtensions( 'skins' )->value;
+               '@phan-var array[] $skins';
                $skinHtml = $this->getFieldsetStart( 'config-skins' );
 
                $skinNames = array_map( 'strtolower', array_keys( $skins ) );
@@ -144,7 +145,8 @@ class WebInstallerOptions extends WebInstallerPage {
                        $this->getFieldsetEnd();
                $this->addHTML( $skinHtml );
 
-               $extensions = $this->parent->findExtensions();
+               $extensions = $this->parent->findExtensions()->value;
+               '@phan-var array[] $extensions';
                $dependencyMap = [];
 
                if ( $extensions ) {
@@ -324,11 +326,16 @@ class WebInstallerOptions extends WebInstallerPage {
                return null;
        }
 
+       /**
+        * @param string $name
+        * @param array $screenshots
+        */
        private function makeScreenshotsLink( $name, $screenshots ) {
                global $wgLang;
                if ( count( $screenshots ) > 1 ) {
                        $links = [];
                        $counter = 1;
+
                        foreach ( $screenshots as $shot ) {
                                $links[] = Html::element(
                                        'a',
@@ -448,7 +455,7 @@ class WebInstallerOptions extends WebInstallerPage {
         * @return bool
         */
        public function submitSkins() {
-               $skins = array_keys( $this->parent->findExtensions( 'skins' ) );
+               $skins = array_keys( $this->parent->findExtensions( 'skins' )->value );
                $this->parent->setVar( '_Skins', $skins );
 
                if ( $skins ) {
@@ -498,7 +505,7 @@ class WebInstallerOptions extends WebInstallerPage {
                        $this->setVar( 'wgRightsIcon', '' );
                }
 
-               $skinsAvailable = array_keys( $this->parent->findExtensions( 'skins' ) );
+               $skinsAvailable = array_keys( $this->parent->findExtensions( 'skins' )->value );
                $skinsToInstall = [];
                foreach ( $skinsAvailable as $skin ) {
                        $this->parent->setVarsFromRequest( [ "skin-$skin" ] );
@@ -519,7 +526,7 @@ class WebInstallerOptions extends WebInstallerPage {
                        $retVal = false;
                }
 
-               $extsAvailable = array_keys( $this->parent->findExtensions() );
+               $extsAvailable = array_keys( $this->parent->findExtensions()->value );
                $extsToInstall = [];
                foreach ( $extsAvailable as $ext ) {
                        $this->parent->setVarsFromRequest( [ "ext-$ext" ] );
index 1b814a2..a7a9d53 100644 (file)
@@ -35,7 +35,7 @@
        "config-wincache": "[https://www.iis.net/downloads/microsoft/wincache-extension WinCache] دامەزراوە",
        "config-db-type": "جۆری داتابەیس:",
        "config-db-host": "خانەخوێی داتابەیس:",
-       "config-db-name": "ناوی بنکەدراوە:",
+       "config-db-name": "ناوی بنکەدراوە (بێ دابڕین (-)):",
        "config-db-install-account": "ھەژماری بەکارھێنەری بۆ دامەزراندن",
        "config-db-username": "ناوی بەکارھێنەری بنکەدراوە:",
        "config-db-password": "تێپەڕوشەی بنکەدراوە",
@@ -56,5 +56,5 @@
        "config-install-step-done": "کرا",
        "config-help": "یارمەتی",
        "mainpagetext": "<strong>میدیاویکی بە سەرکەوتوویی دامەزرا.</strong>",
-       "mainpagedocfooter": "لە [https://meta.wikimedia.org/wiki/Help:Contents ڕێنوێنیی بەکارھێنەران] بۆ زانیاری سەبارەت بە بەکارھێنانی نەرمامێری ویکی کەڵک وەربگرە.\n\n== دەستپێکردن ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings پێرستی ڕێکخستنەکانی شێوەپێدان]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ پرسیارە دووپاتکراوەکانی میدیاویکی (MediaWiki FAQ)]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce پێرستی ئیمەیلی وەشانەکانی میدیاویکی]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources خۆماڵیکردنی ویکیمیدیا بۆ زمانەکەت]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam فێربە چۆن ڕووبەڕووى ئیمەیڵە بێزارکەرەکانی ویکییەکەت دەبیتەوە]"
+       "mainpagedocfooter": "لە [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents ڕێنوێنیی بەکارھێنەران] بۆ زانیاری سەبارەت بە بەکارھێنانی نەرمامێری ویکی کەڵک وەربگرە.\n\n== دەستپێکردن ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings پێرستی ڕێکخستنەکانی شێوەپێدان]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ پرسیارە دووپاتکراوەکانی میدیاویکی (MediaWiki FAQ)]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce پێرستی ئیمەیلی وەشانەکانی میدیاویکی]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources خۆماڵیکردنی ویکیمیدیا بۆ زمانەکەت]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam فێربە چۆن ڕووبەڕووى ئیمەیڵە بێزارکەرەکانی ویکییەکەت دەبیتەوە]"
 }
index e7e653b..b57ed3d 100644 (file)
        "config-no-uri": "<strong>Erreur :</strong> impossible de déterminer l’URI du script actuel.\nInstallation interrompue.",
        "config-no-cli-uri": "<strong>Attention :</strong> aucun <code>--scriptpath</code> n’a été spécifié ; <code>$1</code> sera utilisé par défaut.",
        "config-using-server": "Utilisation du nom de serveur « <nowiki>$1</nowiki> ».",
-       "config-using-uri": "Utilisation de l’URL de serveur « <nowiki>$1$2</nowiki> ».",
+       "config-using-uri": "Utilisation de l’URL de serveur « <nowiki>$1$2</nowiki> ».",
        "config-uploads-not-safe": "<strong>Attention :</strong> votre répertoire par défaut pour les téléversements, <code>$1</code>, est vulnérable, car il peut exécuter n’importe quel script.\nBien que MediaWiki vérifie tous les fichiers téléversés, il est fortement recommandé de [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security fermer cette faille de sécurité] (texte en anglais) avant d’activer les téléversements.",
        "config-no-cli-uploads-check": "'''Attention :''' votre répertoire par défaut pour les imports (<code>$1</code>) n’est pas contrôlé concernant la vulnérabilité d’exécution de scripts arbitraires lors de l’installation CLI.",
        "config-brokenlibxml": "Votre système utilise une combinaison de versions de PHP et libxml2 qui est boguée et peut engendrer des corruptions cachées de données dans MediaWiki et d’autres applications web.\nVeuillez mettre à jour votre système vers libxml2 2.7.3 ou plus récent ([https://bugs.php.net/bug.php?id=45996 anomalie signalée auprès de PHP]).\nInstallation interrompue.",
-       "config-suhosin-max-value-length": "Suhosin est installé et limite la <code>longueur</code> de paramètre GET à $1 octets.\nLe composant ResourceLoader de MediaWiki va répondre en respectant cette limite, mais ses performances seront dégradées. Si possible, vous devriez définir <code>suhosin.get.max_value_length</code> à 1024 ou plus dans le fichier <code>php.ini</code>, et fixer <code>$wgResourceLoaderMaxQueryLength</code> à la même valeur dans <code>LocalSettings.php</code>.",
+       "config-suhosin-max-value-length": "Suhosin est installé et limite la <code>longueur</code> de paramètre GET à $1 octets.\nMediaWiki exige que <code>suhosin.get.max_value_length</code> vaille au moins $2. Désactiver ce paramètre, ou augmenter sa valeur à $3 dans <code>php.ini</code>.",
        "config-using-32bit": "<strong>Attention :</strong> votre système semble utiliser les entiers sur 32 bits. Ceci n’est [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit pas recommandé].",
        "config-db-type": "Type de base de données :",
        "config-db-host": "Nom d’hôte de la base de données :",
-       "config-db-host-help": "Si votre serveur de base de données est sur un serveur différent, saisissez ici son nom d’hôte ou son adresse IP.\n\nSi vous utilisez un hébergement mutualisé, votre hébergeur doit vous avoir fourni le nom d’hôte correct dans sa documentation.\n\nSi vous utilisez MySQL, « localhost » peut ne pas fonctionner comme nom de serveur. S’il ne fonctionne pas, essayez « 127.0.0.1 » comme adresse IP locale.\n\nSi vous utilisez PostgreSQL, laissez ce champ vide pour vous connecter via un socket Unix.",
+       "config-db-host-help": "Si votre serveur de base de données est sur un serveur différent, saisissez ici son nom d’hôte ou son adresse IP.\n\nSi vous utilisez un hébergement mutualisé, votre hébergeur doit vous avoir fourni le nom d’hôte correct dans sa documentation.\n\nSi vous utilisez MySQL, « localhost » peut ne pas fonctionner comme nom de serveur. S’il ne fonctionne pas, essayez « 127.0.0.1 » comme adresse IP locale.\n\nSi vous utilisez PostgreSQL, laissez ce champ vide pour vous connecter via un socket Unix.",
        "config-db-wiki-settings": "Identifier ce wiki",
        "config-db-name": "Nom de la base de données (sans tirets) :",
        "config-db-name-help": "Choisissez un nom qui identifie votre wiki.\nIl ne doit pas contenir d’espaces.\n\nSi vous utilisez un hébergement web partagé, votre hébergeur vous fournira un nom spécifique de base de données à utiliser, ou bien vous permet de créer des bases de données via un panneau de contrôle.",
        "config-missing-db-host": "Vous devez entrer une valeur pour « {{int:config-db-host}} ».",
        "config-invalid-db-name": "Nom de la base de données invalide (« $1 »).\nUtiliser seulement les lettres ASCII (a-z, A-Z), les chiffres (0-9), les caractères de soulignement (_) et les tirets (-).",
        "config-invalid-db-prefix": "Préfixe de la base de données non valide « $1 ».\nUtiliser seulement les lettres ASCII (a-z, A-Z), les chiffres (0-9), les caractères de soulignement (_) et les tirets (-).",
-       "config-connection-error": "$1.\n\nVérifier le nom d’hôte, le nom d’utilisateur et le mot de passe ci-dessous puis réessayer. Si vous utilisez « localhost » comme hôte de base de données, essayez d’utiliser « 127.0.0.1 » à la place (ou inversement).",
+       "config-connection-error": "$1.\n\nVérifier le nom d’hôte, le nom d’utilisateur et le mot de passe ci-dessous puis réessayer. Si vous utilisez « localhost » comme hôte de base de données, essayez d’utiliser « 127.0.0.1 » à la place (ou inversement).",
        "config-invalid-schema": "Schéma invalide pour MediaWiki « $1 ».\nUtiliser seulement les lettres ASCII (a-z, A-Z), les chiffres (0-9) et les caractères de soulignement (_).",
        "config-postgres-old": "PostgreSQL $1 ou version ultérieure est requis. Vous avez $2.",
        "config-sqlite-name-help": "Choisir un nom qui identifie votre wiki.\nNe pas utiliser d'espaces ni de traits d'union.\nIl sera utilisé pour le fichier de données SQLite.",
        "config-sqlite-cant-create-db": "Impossible de créer le fichier de base de données <code>$1</code>.",
        "config-sqlite-fts3-downgrade": "PHP n’a pas trouvé la prise en charge FTS3, les tables sont restreintes.",
        "config-can-upgrade": "Il y a des tables MediaWiki dans cette base de données.\nPour les mettre au niveau de MediaWiki $1, cliquez sur '''Continuer'''.",
-       "config-upgrade-error": "Une erreur est survenue durant la mise à jour des tables MédiaWiki de votre base de données.\n\nPour plus d'informations voir le journal ci-dessus, pour réessayer, cliquez sur <strong>Continuer</strong>.",
+       "config-upgrade-error": "Une erreur est survenue durant la mise à jour des tables MediaWiki de votre base de données.\n\nPour plus d'informations voir le journal ci-dessus, pour réessayer, cliquez sur <strong>Continuer</strong>.",
        "config-upgrade-done": "Mise à jour terminée.\n\nVous pouvez maintenant [$1 commencer à utiliser votre wiki].\n\nSi vous souhaitez régénérer votre fichier <code>LocalSettings.php</code>, cliquez sur le bouton ci-dessous.\nCeci '''n'est pas recommandé''' sauf si vous rencontrez des problèmes avec votre wiki.",
        "config-upgrade-done-no-regenerate": "Mise à jour terminée.\n\nVous pouvez maintenant [$1 commencer à utiliser votre wiki].",
        "config-regenerate": "Regénérer LocalSettings.php →",
        "config-ns-site-name": "Même nom que le wiki : $1",
        "config-ns-other": "Autre (préciser)",
        "config-ns-other-default": "MonWiki",
-       "config-project-namespace-help": "Suivant l’exemple de Wikipédia, plusieurs wikis gardent leurs pages de politique séparées de leurs pages de contenu, dans un '''espace de noms de niveau projet''' propre.\nTous les titres de page de cet espace de noms commence par un préfixe défini, que vous pouvez spécifier ici.\nTraditionnellement, ce préfixe est dérivé du nom du wiki, et ne peut contenir de caractères de ponctuation tels que « # » ou « : ».",
+       "config-project-namespace-help": "Suivant l’exemple de Wikipédia, plusieurs wikis gardent leurs pages de politique séparées de leurs pages de contenu, dans un '''espace de noms de niveau projet''' propre.\nTous les titres de page de cet espace de noms commence par un préfixe défini, que vous pouvez spécifier ici.\nTraditionnellement, ce préfixe est dérivé du nom du wiki, et ne peut contenir de caractères de ponctuation tels que « # » ou « : ».",
        "config-ns-invalid": "L'espace de noms spécifié « <nowiki>$1</nowiki> » n'est pas valide.\nSpécifiez un espace de noms différent pour le projet.",
        "config-ns-conflict": "L'espace de noms spécifié « <nowiki>$1</nowiki> » est en conflit avec un espace de noms par défaut de MediaWiki.\nChoisir un autre espace de noms pour le projet.",
        "config-admin-box": "Compte administrateur",
        "config-skins": "Habillages",
        "config-skins-help": "Les habillages listés ci-dessous ont été détectés dans votre répertoire <code>./skins</code>. Vous devez en activer au moins un, et choisir celui par défaut.",
        "config-skins-use-as-default": "Utiliser cet habillage par défaut",
-       "config-skins-missing": "Aucun habillage trouvé ; MédiaWiki utilisera un habillage de secours jusqu’à ce que vous en installiez un approprié.",
+       "config-skins-missing": "Aucun habillage trouvé ; MediaWiki utilisera un habillage de secours jusqu’à ce que vous en installiez un approprié.",
        "config-skins-must-enable-some": "Vous devez choisir au moins un habillage à activer.",
        "config-skins-must-enable-default": "L’habillage choisi par défaut doit être activé.",
        "config-install-alreadydone": "'''Attention''': Vous semblez avoir déjà installé MediaWiki et tentez de l'installer à nouveau.\nS'il vous plaît, allez à la page suivante.",
        "config-install-extension-tables": "Création de tables pour les extensions activées",
        "config-install-mainpage-failed": "Impossible d’insérer la page principale : $1",
        "config-install-done": "<strong>Félicitations!</strong>\nVous avez installé MediaWiki.\n\nLe programme d'installation a généré un fichier <code>LocalSettings.php</code>. Il contient tous les paramètres de votre configuration.\n\nVous devrez le télécharger et le mettre à la racine de votre installation wiki (dans le même répertoire que index.php). Le téléchargement devrait démarrer automatiquement.\n\nSi le téléchargement n'a pas été proposé, ou que vous l'avez annulé, vous pouvez redémarrer le téléchargement en cliquant ce lien :\n\n$3\n\n<strong>Note :</strong> Si vous ne le faites pas maintenant, ce fichier de configuration généré ne sera pas disponible plus tard si vous quittez l'installation sans le télécharger.\n\nLorsque c'est fait, vous pouvez <strong>[$2 accéder à votre wiki]</strong> .",
-       "config-install-done-path": "<strong>Félicitations !</strong>\nVous avez installé MédiaWiki.\n\nL’installeur a généré un fichier <code>LocalSettings.php</code>.\nIl contient toute votre configuration.\n\nVous devez le télécharger et le mettre dans <code>$4</code>. Le téléchargement devrait avoir démarré automatiquement.\n\nSi le téléchargement n’a pas été proposé ou si vous l’avez annulé, vous pouvez le redémarrer en cliquant sur le lien ci-dessous :\n\n$3\n\n<strong>Note :</strong> Si vous ne le faites pas maintenant, ce fichier de configuration généré ne sera plus disponible ultérieurement si vous quittez l’installation sans le télécharger.\n\nUne fois ceci fait, vous pouvez <strong>[$2 entrer dans votre wiki]</strong>.",
-       "config-install-success": "MédiaWiki a été installé correctement. Vous pouvez maintenant visiter <$1$2> pour voir votre wiki.\nSi vous avez des questions, consultez notre foire aux questions :\n<https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ> ou utilisez un des\nforums de support liés sur cette page.",
+       "config-install-done-path": "<strong>Félicitations !</strong>\nVous avez installé MediaWiki.\n\nL’installeur a généré un fichier <code>LocalSettings.php</code>.\nIl contient toute votre configuration.\n\nVous devez le télécharger et le mettre dans <code>$4</code>. Le téléchargement devrait avoir démarré automatiquement.\n\nSi le téléchargement n’a pas été proposé ou si vous l’avez annulé, vous pouvez le redémarrer en cliquant sur le lien ci-dessous :\n\n$3\n\n<strong>Note :</strong> Si vous ne le faites pas maintenant, ce fichier de configuration généré ne sera plus disponible ultérieurement si vous quittez l’installation sans le télécharger.\n\nUne fois ceci fait, vous pouvez <strong>[$2 entrer dans votre wiki]</strong>.",
+       "config-install-success": "MediaWiki a été installé correctement. Vous pouvez maintenant visiter <$1$2> pour voir votre wiki.\nSi vous avez des questions, consultez notre foire aux questions :\n<https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ> ou utilisez un des\nforums de support liés sur cette page.",
        "config-install-db-success": "La base de données a été bien installée",
        "config-download-localsettings": "Télécharger <code>LocalSettings.php</code>",
        "config-help": "aide",
        "config-skins-screenshots": "$1 (captures d’écran : $2)",
        "config-extensions-requires": "$1 (nécessite $2)",
        "config-screenshot": "Captures d’écrans",
-       "config-extension-not-found": "Impossible de trouver le fichier d’inscription pour l’extension « $1 »",
-       "config-extension-dependency": "Une erreur de dépendance s’est produite en installant l’extension « $1 » : $2",
+       "config-extension-not-found": "Impossible de trouver le fichier d’inscription pour l’extension « $1 »",
+       "config-extension-dependency": "Une erreur de dépendance s’est produite en installant l’extension « $1 » : $2",
        "mainpagetext": "<strong>MediaWiki a été installé.</strong>",
        "mainpagedocfooter": "Consultez le [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Guide de l’utilisateur] pour plus d’informations sur l’utilisation de ce logiciel de wiki.\n\n== Pour démarrer ==\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Configuration_settings Liste des paramètres de configuration]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ/fr Questions courantes sur MediaWiki]\n* [https://lists.wikimedia.org/mailman/listinfo/mediawiki-announce Liste de discussion sur les distributions de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation#Translation_resources Adaptez MediaWiki dans votre langue]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Combating_spam Apprendre comment lutter contre le pourriel dans votre wiki]"
 }
index eae79b0..e5ebb42 100644 (file)
        "config-restart": "Si, reinitia lo",
        "config-welcome": "=== Verificationes del ambiente ===\nVerificationes de base essera ora exequite pro determinar si iste ambiente es apte pro le installation de MediaWiki.\nNon oblida de includer iste information si tu cerca adjuta pro completar le installation.",
        "config-welcome-section-copyright": "=== Copyright and Terms ===\n\n$1\n\nIste programma es software libere; vos pote redistribuer lo e/o modificar lo sub le conditiones del Licentia Public General de GNU publicate per le Free Software Foundation; version 2 del Licentia, o (a vostre option) qualcunque version posterior.\n\nIste programma es distribuite in le sperantia que illo sia utile, ma '''sin garantia''', sin mesmo le implicite garantia de '''commercialisation''' o '''aptitude pro un proposito particular'''.\nVide le Licentia Public General de GNU pro plus detalios.\n\nVos deberea haber recipite [$2 un exemplar del Licentia Public General de GNU] con iste programma; si non, scribe al Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA, o [https://www.gnu.org/copyleft/gpl.html lege lo in linea].",
-       "config-sidebar": "* [https://www.mediawiki.org Pagina principal de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Guida pro usatores]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Guida pro administratores]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ FAQ]\n----\n* <doclink href=Readme>Lege me</doclink>\n* <doclink href=ReleaseNotes>Notas de iste version</doclink>\n* <doclink href=Copying>Conditiones de copia</doclink>\n* <doclink href=UpgradeDoc>Actualisation</doclink>",
+       "config-sidebar": "* [https://www.mediawiki.org Pagina principal de MediaWiki]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Help:Contents Guida pro usatores]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Contents Guida pro administratores]\n* [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:FAQ FAQ]",
+       "config-sidebar-readme": "Lege me",
+       "config-sidebar-relnotes": "Notas de iste version",
+       "config-sidebar-license": "Conditiones de copia",
+       "config-sidebar-upgrade": "Actualisation",
        "config-env-good": "Le ambiente ha essite verificate.\nTu pote installar MediaWiki.",
        "config-env-bad": "Le ambiente ha essite verificate.\nTu non pote installar MediaWiki.",
        "config-env-php": "PHP $1 es installate.",
@@ -79,7 +83,7 @@
        "config-uploads-not-safe": "'''Aviso:''' Le directorio predefinite pro files incargate <code>$1</code> es vulnerabile al execution arbitrari de scripts.\nBen que MediaWiki verifica tote le files incargate contra le menacias de securitate, il es altemente recommendate [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security remediar iste vulnerabilitate de securitate] ante de activar le incargamento de files.",
        "config-no-cli-uploads-check": "'''Attention:''' Le directorio predefinite pro files incargate (<code>$1</code>) non es verificate contra le vulnerabilitate\nal execution arbitrari de scripts durante le installation de CLI.",
        "config-brokenlibxml": "Vostre systema ha un combination de versiones de PHP e libxml2 que es defectuose e pote causar corruption celate de datos in MediaWiki e altere applicationes web.\nActualisa a libxml2 2.7.3 o plus recente ([https://bugs.php.net/bug.php?id=45996 problema reportate presso PHP]).\nInstallation abortate.",
-       "config-suhosin-max-value-length": "Suhosin es installate e limita parametro <code>length</code> de GET a $1 bytes.\nLe componente ResourceLoader de MediaWiki va contornar iste limite, ma isto prejudicara le rendimento.\nSi possibile, tu deberea mitter <code>suhosin.get.max_value_length</code> a 1024 o superior in <code>php.ini</code>, e mitter <code>$wgResourceLoaderMaxQueryLength</code> al mesme valor in <code>LocalSettings.php</code>.",
+       "config-suhosin-max-value-length": "Suhosin es installate e limita parametro <code>length</code> de GET a $1 bytes.\nMediaWiki require que <code>suhosin.get.max_value_length</code> sia al minus $2. Disactiva iste parametro, o augmenta iste valor a $3 in <code>php.ini</code>.",
        "config-using-32bit": "<strong>Attention:</strong> tu systema pare operar con integres de 32 bits. Isto [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit non es recommendate].",
        "config-db-type": "Typo de base de datos:",
        "config-db-host": "Servitor de base de datos:",
index cb72d91..f385ab5 100644 (file)
        "config-uploads-not-safe": "<strong>Attenzione:</strong> la directory predefinita per i caricamenti <code>$1</code> è vulnerabile all'esecuzione arbitraria di script.\nAnche se, a difesa della sicurezza, MediaWiki controlla tutti i file caricati, è fortemente raccomandato di [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security chiudere questa minaccia] prima di abilitare i caricamenti.",
        "config-no-cli-uploads-check": "<strong>Attenzione:</strong> la directory predefinita per i caricamenti (<code>$1</code>) non è stata verificata per la vulnerabilità sull'esecuzione arbitraria di script durante l'installazione da linea di comando.",
        "config-brokenlibxml": "Il tuo sistema ha una combinazione di versioni di PHP e libxml2 che è difettosa e che può provocare un danneggiamento non visibile di dati in MediaWiki ed in altre applicazioni per il web.\nAggiorna a libxml2 2.7.3 o successivo ([https://bugs.php.net/bug.php?id=45996 il bug è studiato dal lato PHP]).\nInstallazione interrotta.",
-       "config-suhosin-max-value-length": "Suhosin è installato e limita il parametro GET <code>length</code> a $1 byte.\nIl componente MediaWiki ResourceLoader funzionerà aggirando questo limite, ma riducendo le prestazioni.\nSe possibile, dovresti impostare <code>suhosin.get.max_value_length</code> a 1024 o superiore in <code>php.ini</code>, ed impostare <code>$wgResourceLoaderMaxQueryLength</code> allo stesso valore in <code>LocalSettings.php</code>.",
+       "config-suhosin-max-value-length": "Suhosin è installato e limita il parametro GET <code>length</code> a $1 byte.\nMediaWiki richiede un valore per <code>suhosin.get.max_value_length</code> di almeno $2. Disattiva questa impostazione, o aumenta questo valore a $3 in <code>php.ini</code>.",
        "config-using-32bit": "<strong>Attenzione</strong> sembra che il tuo sistema utilizzi interi a 32-bit, ciò [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit non è raccomandato].",
        "config-db-type": "Tipo di database:",
        "config-db-host": "Host del database:",
index 5da1914..511b0da 100644 (file)
        "config-uploads-not-safe": "<strong>警告:</strong> アップロードの既定ディレクトリ <code>$1</code> に、任意のスクリプト実行に関する脆弱性があります。\nMediaWiki はアップロードされたファイルのセキュリティ上の脅威を確認しますが、アップロードを有効化する前に、[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security このセキュリティ上の脆弱性を解決する]ことを強く推奨します。",
        "config-no-cli-uploads-check": "<strong>警告:</strong> アップロード用のデフォルトディレクトリ (<code>$1</code>) が、CLIでのインストール中に任意のスクリプト実行の脆弱性チェックを受けていません。",
        "config-brokenlibxml": "このシステムで使われているPHPとlibxml2のバージョンのこの組み合わせにはバグがあります。具体的には、MediaWikiやその他のウェブアプリケーションでhiddenデータが破損する可能性があります。\nlibxml2を2.7.3以降のバージョンにアップグレードしてください([https://bugs.php.net/bug.php?id=45996 PHPでのバグ情報])。\nインストールを終了します。",
-       "config-suhosin-max-value-length": "Suhosin がインストールされており、GET パラメーターの <code>length</code> を $1 バイトに制限しています。\nMediaWiki の ResourceLoader コンポーネントはこの制限を回避しますが、パフォーマンスは低下します。\n可能な限り、<code>php.ini</code> で <code>suhosin.get.max_value_length</code> を 1024 以上に設定し、同じ値を <code>LocalSettings.php</code> 内で <code>$wgResourceLoaderMaxQueryLength</code> に設定してください。",
+       "config-suhosin-max-value-length": "Suhosin がインストールされており、GET パラメーターの <code>length</code> を $1 バイトに制限しています。(訳注:\nMediaWiki の ResourceLoader コンポーネントはこの制限を回避しますが、パフォーマンスは低下します。)\n可能な限り、 <code>suhosin.get.max_value_length</code> を $2 以上に設定します。これを無効に変更するか、<code>php.ini</code> で $3 に増加してください。",
        "config-using-32bit": "<strong>警告:</strong>システムが32ビットで動作しているようです。 これは[https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit 非推奨]です。",
        "config-db-type": "データベースの種類:",
        "config-db-host": "データベースのホスト:",
index 7a13bde..21ca17c 100644 (file)
        "config-uploads-not-safe": "<strong>Waarschuwing:</strong> uw uploadmap <code>$1</code> kan gebruikt worden voor het arbitrair uitvoeren van scripts.\nHoewel MediaWiki alle toegevoegde bestanden controleert op bedreigingen, is het zeer aan te bevelen het [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:Security#Upload_security beveiligingslek te verhelpen] alvorens uploads in te schakelen.",
        "config-no-cli-uploads-check": "''Waarschuwing:'' uw standaardmap voor uploads (<code>$1</code>) wordt niet gecontroleerd op kwetsbaarheden voor het uitvoeren van willekeurige scripts gedurende de CLI-installatie.",
        "config-brokenlibxml": "Uw systeem heeft een combinatie van PHP- en libxml2-versies geïnstalleerd die is foutgevoelig is en kan leiden tot onzichtbare beschadiging van gegevens in MediaWiki en andere webapplicaties.\nUpgrade naar libxml2 2.7.3 of hoger([https://bugs.php.net/bug.php?id=45996 bij PHP gerapporteerde fout]).\nDe installatie wordt afgebroken.",
-       "config-suhosin-max-value-length": "Suhosin is geïnstalleerd en beperkt de GET-parameter <code>length</code> tot $1 bytes.\nDe ResourceLoader van MediaWiki omzeilt deze beperking, maar dat is slecht voor de prestaties.\nAls het mogelijk is, moet u de waarde \"<code>suhosin.get.max_value_length</code>\" in <code>php.ini</code> instellen op 1024 of hoger en <code>$wgResourceLoaderMaxQueryLength</code> in LocalSettings.php op dezelfde waarde instellen.",
+       "config-suhosin-max-value-length": "Suhosin is geïnstalleerd en beperkt de GET-parameter <code>length</code> tot $1 bytes.\nMediaWiki vereist dat <code>suhosin.get.max_value_length</code> ten minste $2 is. Schakel deze instelling uit, of verhoog deze in <code>php.ini</code> naar $3.",
        "config-using-32bit": "<strong>Pas op:</strong> uw systeem lijkt met 32-bit integers te werken. Dit is [https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:32-bit anders dan aangeraden].",
        "config-db-type": "Databasetype:",
        "config-db-host": "Databasehost:",
index fc66bdb..f3f211e 100644 (file)
@@ -24,7 +24,8 @@
                        "Sethakill",
                        "Peter Bowman",
                        "Ankam",
-                       "Railfail536"
+                       "Railfail536",
+                       "Rail"
                ]
        },
        "config-desc": "Instalator MediaWiki",
index b4046a6..33b05b8 100644 (file)
@@ -276,8 +276,8 @@ class RefreshLinksJob extends Job {
                $title = $page->getTitle();
                // Get the latest ID since acquirePageLock() in runForTitle() flushed the transaction.
                // This is used to detect edits/moves after loadPageData() but before the scope lock.
-               // The works around the chicken/egg problem of determining the scope lock key name.
-               $latest = $title->getLatestRevID( Title::GAID_FOR_UPDATE );
+               // The works around the chicken/egg problem of determining the scope lock key name
+               $latest = $title->getLatestRevID( Title::READ_LATEST );
 
                $triggeringRevisionId = $this->params['triggeringRevisionId'] ?? null;
                if ( $triggeringRevisionId && $triggeringRevisionId !== $latest ) {
index 5e7485c..f511229 100644 (file)
@@ -48,6 +48,9 @@ class MemoizedCallable {
        /** @var string Unique name of callable; used for cache keys. */
        private $callableName;
 
+       /** @var int */
+       private $ttl;
+
        /**
         * @throws InvalidArgumentException if $callable is not a callable.
         * @param callable $callable Function or method to memoize.
index 54d43d3..b036f05 100644 (file)
@@ -7,6 +7,10 @@
  * @since 1.27
  */
 class ComposerInstalled {
+       /**
+        * @var array[]
+        */
+       private $contents;
 
        /**
         * @param string $location
@@ -18,7 +22,7 @@ class ComposerInstalled {
        /**
         * Dependencies currently installed according to installed.json
         *
-        * @return array
+        * @return array[]
         */
        public function getInstalledDependencies() {
                $deps = [];
index 62231a8..f92759b 100644 (file)
@@ -7,6 +7,10 @@
  * @since 1.25
  */
 class ComposerJson {
+       /**
+        * @var array[]
+        */
+       private $contents;
 
        /**
         * @param string $location
@@ -18,7 +22,7 @@ class ComposerJson {
        /**
         * Dependencies as specified by composer.json
         *
-        * @return array
+        * @return string[]
         */
        public function getRequiredDependencies() {
                $deps = [];
index c5b5f00..7f6b875 100644 (file)
@@ -7,6 +7,10 @@
  * @since 1.25
  */
 class ComposerLock {
+       /**
+        * @var array[]
+        */
+       private $contents;
 
        /**
         * @param string $location
@@ -18,7 +22,7 @@ class ComposerLock {
        /**
         * Dependencies currently installed according to composer.lock
         *
-        * @return array
+        * @return array[]
         */
        public function getInstalledDependencies() {
                $deps = [];
index 5534cbd..26f3d3a 100644 (file)
@@ -73,7 +73,7 @@ class FSFileBackend extends FileBackendStore {
        /** @var string Required OS username to own files */
        protected $fileOwner;
 
-       /** @var bool Whether the OS is Windows (otherwise assumed Unix-like)*/
+       /** @var bool Whether the OS is Windows (otherwise assumed Unix-like) */
        protected $isWindows;
        /** @var string OS username running this script */
        protected $currentUser;
@@ -556,9 +556,7 @@ class FSFileBackend extends FileBackendStore {
                $contRoot = $this->containerFSRoot( $shortCont, $fullCont ); // must be valid
                $dir = ( $dirRel != '' ) ? "{$contRoot}/{$dirRel}" : $contRoot;
                AtEase::suppressWarnings();
-               if ( is_dir( $dir ) ) {
-                       rmdir( $dir ); // remove directory if empty
-               }
+               rmdir( $dir ); // remove directory if empty
                AtEase::restoreWarnings();
 
                return $status;
index 0917d9a..d7d428e 100644 (file)
@@ -1587,7 +1587,7 @@ abstract class FileBackendStore extends FileBackend {
                                // Validate and sanitize the relative path (backend-specific)
                                $relPath = $this->resolveContainerPath( $shortCont, $relPath );
                                if ( $relPath !== null ) {
-                                       // Prepend any wiki ID prefix to the container name
+                                       // Prepend any domain ID prefix to the container name
                                        $container = $this->fullContainerName( $shortCont );
                                        if ( self::isValidContainerName( $container ) ) {
                                                // Validate and sanitize the container name (backend-specific)
@@ -1722,7 +1722,7 @@ abstract class FileBackendStore extends FileBackend {
        }
 
        /**
-        * Get the full container name, including the wiki ID prefix
+        * Get the full container name, including the domain ID prefix
         *
         * @param string $container
         * @return string
index f3bbecb..82f1962 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 use Wikimedia\AtEase\AtEase;
+use Wikimedia\Timestamp\ConvertibleTimestamp;
 
 /**
  * Simulation of a backend storage in memory.
@@ -56,7 +57,7 @@ class MemoryFileBackend extends FileBackendStore {
 
                $this->files[$dst] = [
                        'data' => $params['content'],
-                       'mtime' => wfTimestamp( TS_MW, time() )
+                       'mtime' => ConvertibleTimestamp::convert( TS_MW, time() )
                ];
 
                return $status;
@@ -83,7 +84,7 @@ class MemoryFileBackend extends FileBackendStore {
 
                $this->files[$dst] = [
                        'data' => $data,
-                       'mtime' => wfTimestamp( TS_MW, time() )
+                       'mtime' => ConvertibleTimestamp::convert( TS_MW, time() )
                ];
 
                return $status;
@@ -116,7 +117,7 @@ class MemoryFileBackend extends FileBackendStore {
 
                $this->files[$dst] = [
                        'data' => $this->files[$src]['data'],
-                       'mtime' => wfTimestamp( TS_MW, time() )
+                       'mtime' => ConvertibleTimestamp::convert( TS_MW, time() )
                ];
 
                return $status;
index c58924b..820634c 100644 (file)
@@ -1090,11 +1090,11 @@ class SwiftFileBackend extends FileBackendStore {
        protected function doStreamFile( array $params ) {
                $status = $this->newStatus();
 
-               $flags = !empty( $params['headless'] ) ? StreamFile::STREAM_HEADLESS : 0;
+               $flags = !empty( $params['headless'] ) ? HTTPFileStreamer::STREAM_HEADLESS : 0;
 
                list( $srcCont, $srcRel ) = $this->resolveStoragePathReal( $params['src'] );
                if ( $srcRel === null ) {
-                       StreamFile::send404Message( $params['src'], $flags );
+                       HTTPFileStreamer::send404Message( $params['src'], $flags );
                        $status->fatal( 'backend-fail-invalidpath', $params['src'] );
 
                        return $status;
@@ -1102,7 +1102,7 @@ class SwiftFileBackend extends FileBackendStore {
 
                $auth = $this->getAuthentication();
                if ( !$auth || !is_array( $this->getContainerStat( $srcCont ) ) ) {
-                       StreamFile::send404Message( $params['src'], $flags );
+                       HTTPFileStreamer::send404Message( $params['src'], $flags );
                        $status->fatal( 'backend-fail-stream', $params['src'] );
 
                        return $status;
@@ -1111,7 +1111,7 @@ class SwiftFileBackend extends FileBackendStore {
                // If "headers" is set, we only want to send them if the file is there.
                // Do not bother checking if the file exists if headers are not set though.
                if ( $params['headers'] && !$this->fileExists( $params ) ) {
-                       StreamFile::send404Message( $params['src'], $flags );
+                       HTTPFileStreamer::send404Message( $params['src'], $flags );
                        $status->fatal( 'backend-fail-stream', $params['src'] );
 
                        return $status;
@@ -1301,6 +1301,9 @@ class SwiftFileBackend extends FileBackendStore {
        }
 
        protected function doExecuteOpHandlesInternal( array $fileOpHandles ) {
+               /** @var SwiftFileOpHandle[] $fileOpHandles */
+               '@phan-var SwiftFileOpHandle[] $fileOpHandles';
+
                /** @var StatusValue[] $statuses */
                $statuses = [];
 
@@ -1316,7 +1319,6 @@ class SwiftFileBackend extends FileBackendStore {
                // Split the HTTP requests into stages that can be done concurrently
                $httpReqsByStage = []; // map of (stage => index => HTTP request)
                foreach ( $fileOpHandles as $index => $fileOpHandle ) {
-                       /** @var SwiftFileOpHandle $fileOpHandle */
                        $reqs = $fileOpHandle->httpOp;
                        // Convert the 'url' parameter to an actual URL using $auth
                        foreach ( $reqs as $stage => &$req ) {
index c366a0f..8697f9f 100644 (file)
@@ -34,8 +34,8 @@ abstract class FileBackendStoreOpHandle {
        public $backend;
        /** @var array */
        public $resourcesToClose = [];
-
-       public $call; // string; name that identifies the function called
+       /** @var callable name that identifies the function called */
+       public $call;
 
        /**
         * Close all open file handles
index 1937e37..cce32ba 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 use Wikimedia\AtEase\AtEase;
+use Wikimedia\Timestamp\ConvertibleTimestamp;
 
 /**
  * Class representing a non-directory file on the file system
@@ -68,7 +69,11 @@ class FSFile {
         * @return int|bool
         */
        public function getSize() {
-               return filesize( $this->path );
+               AtEase::suppressWarnings();
+               $size = filesize( $this->path );
+               AtEase::restoreWarnings();
+
+               return $size;
        }
 
        /**
@@ -81,7 +86,7 @@ class FSFile {
                $timestamp = filemtime( $this->path );
                AtEase::restoreWarnings();
                if ( $timestamp !== false ) {
-                       $timestamp = wfTimestamp( TS_MW, $timestamp );
+                       $timestamp = ConvertibleTimestamp::convert( TS_MW, $timestamp );
                }
 
                return $timestamp;
index 6478a61..83dcc6b 100644 (file)
@@ -152,7 +152,7 @@ abstract class QuorumLockManager extends LockManager {
         * This is all or nothing; if any key is already pledged then this totally fails.
         *
         * @param int $bucket
-        * @param callable $callback Pledge method taking a server name and yeilding a StatusValue
+        * @param callable $callback Pledge method taking a server name and yielding a StatusValue
         * @return StatusValue
         */
        final protected function collectPledgeQuorum( $bucket, callable $callback ) {
@@ -194,7 +194,7 @@ abstract class QuorumLockManager extends LockManager {
         * Attempt to release pledges with the peers for a bucket
         *
         * @param int $bucket
-        * @param callable $callback Pledge method taking a server name and yeilding a StatusValue
+        * @param callable $callback Pledge method taking a server name and yielding a StatusValue
         * @return StatusValue
         */
        final protected function releasePledges( $bucket, callable $callback ) {
index 9d66326..16cd5ca 100644 (file)
@@ -68,6 +68,9 @@ class XmlTypeCheck {
         */
        protected $stackDepth = 0;
 
+       /** @var callable|null */
+       protected $filterCallback;
+
        /**
         * @var array Additional parsing options
         */
index 51f7316..77a7883 100644 (file)
@@ -46,7 +46,7 @@ class MultiWriteBagOStuff extends BagOStuff {
        /**
         * $params include:
         *   - caches: A numbered array of either ObjectFactory::getObjectFromSpec
-        *      arrays yeilding BagOStuff objects or direct BagOStuff objects.
+        *      arrays yielding BagOStuff objects or direct BagOStuff objects.
         *      If using the former, the 'args' field *must* be set.
         *      The first cache is the primary one, being the first to
         *      be read in the fallback chain. Writes happen to all stores
index ff87829..9f953e1 100644 (file)
@@ -47,9 +47,9 @@ class ReplicatedBagOStuff extends BagOStuff {
 
        /**
         * Constructor. Parameters are:
-        *   - writeFactory: ObjectFactory::getObjectFromSpec array yeilding BagOStuff.
+        *   - writeFactory: ObjectFactory::getObjectFromSpec array yielding BagOStuff.
         *      This object will be used for writes (e.g. the master DB).
-        *   - readFactory: ObjectFactory::getObjectFromSpec array yeilding BagOStuff.
+        *   - readFactory: ObjectFactory::getObjectFromSpec array yielding BagOStuff.
         *      This object will be used for reads (e.g. a replica DB).
         *   - sessionConsistencyWindow: Seconds to read from the master source for a key
         *      after writing to it. [Default: ReplicatedBagOStuff::MAX_WRITE_DELAY]
index 77b029f..5d33e69 100644 (file)
@@ -60,7 +60,7 @@ class LBFactoryMulti extends LBFactory {
        private $masterTemplateOverrides = [];
        /** @var array[] Map of (host => server config map overrides) for main and external servers */
        private $templateOverridesByServer = [];
-       /**  @var string[]|bool[] A map of section name to read-only message */
+       /** @var string[]|bool[] A map of section name to read-only message */
        private $readOnlyBySection = [];
 
        /** @var string An ILoadMonitor class */
@@ -85,7 +85,7 @@ class LBFactoryMulti extends LBFactory {
         * data can be before the load balancer tries to avoid using it. The map can have 'is static'
         * set to disable blocking  replication sync checks (intended for archive servers with
         * unchanging data).
-
+        *
         * @see LBFactory::__construct()
         * @param array $conf Additional parameters include:
         *   - hostsByName                 Optional (hostname => IP address) map.
index eb645cc..343e35c 100644 (file)
@@ -90,6 +90,10 @@ class RedisConnectionPool implements LoggerAwareInterface {
                if ( !isset( $options['serializer'] ) || $options['serializer'] === 'php' ) {
                        $this->serializer = Redis::SERIALIZER_PHP;
                } elseif ( $options['serializer'] === 'igbinary' ) {
+                       if ( !defined( 'Redis::SERIALIZER_IGBINARY' ) ) {
+                               throw new InvalidArgumentException(
+                                       __CLASS__ . ': configured serializer "igbinary" not available' );
+                       }
                        $this->serializer = Redis::SERIALIZER_IGBINARY;
                } elseif ( $options['serializer'] === 'none' ) {
                        $this->serializer = Redis::SERIALIZER_NONE;
index d27643c..d49e3c5 100644 (file)
@@ -22,6 +22,8 @@
  * @since 1.25
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This class formats block log entries.
  *
@@ -138,7 +140,9 @@ class BlockLogFormatter extends LogFormatter {
                $linkRenderer = $this->getLinkRenderer();
                if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
                        || !( $subtype === 'block' || $subtype === 'reblock' )
-                       || !$this->context->getUser()->isAllowed( 'block' )
+                       || !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->context->getUser(), 'block' )
                ) {
                        return '';
                }
index e05357c..23c582c 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
+
 class ContentModelLogFormatter extends LogFormatter {
        protected function getMessageParameters() {
                $lang = $this->context->getLanguage();
@@ -12,7 +14,9 @@ class ContentModelLogFormatter extends LogFormatter {
        public function getActionLinks() {
                if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
                        || $this->entry->getSubtype() !== 'change'
-                       || !$this->context->getUser()->isAllowed( 'editcontentmodel' )
+                       || !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->context->getUser(), 'editcontentmodel' )
                ) {
                        return '';
                }
index 3bc19ff..652c36a 100644 (file)
@@ -23,6 +23,7 @@
  * @since 1.22
  */
 
+use MediaWiki\MediaWikiServices;
 use MediaWiki\Storage\RevisionRecord;
 
 /**
@@ -31,6 +32,12 @@ use MediaWiki\Storage\RevisionRecord;
  * @since 1.19
  */
 class DeleteLogFormatter extends LogFormatter {
+       /** @var array|null */
+       private $parsedParametersDeleteLog;
+
+       /**
+        * @inheritDoc
+        */
        protected function getMessageKey() {
                $key = parent::getMessageKey();
                if ( in_array( $this->entry->getSubtype(), [ 'event', 'revision' ] ) ) {
@@ -50,8 +57,11 @@ class DeleteLogFormatter extends LogFormatter {
                return $key;
        }
 
+       /**
+        * @inheritDoc
+        */
        protected function getMessageParameters() {
-               if ( isset( $this->parsedParametersDeleteLog ) ) {
+               if ( $this->parsedParametersDeleteLog !== null ) {
                        return $this->parsedParametersDeleteLog;
                }
 
@@ -136,7 +146,8 @@ class DeleteLogFormatter extends LogFormatter {
        public function getActionLinks() {
                $user = $this->context->getUser();
                $linkRenderer = $this->getLinkRenderer();
-               if ( !$user->isAllowed( 'deletedhistory' )
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( !$permissionManager->userHasRight( $user, 'deletedhistory' )
                        || $this->entry->isDeleted( LogPage::DELETED_ACTION )
                ) {
                        return '';
@@ -145,7 +156,7 @@ class DeleteLogFormatter extends LogFormatter {
                switch ( $this->entry->getSubtype() ) {
                        case 'delete': // Show undelete link
                        case 'delete_redir':
-                               if ( $user->isAllowed( 'undelete' ) ) {
+                               if ( $permissionManager->userHasRight( $user, 'undelete' ) ) {
                                        $message = 'undeletelink';
                                } else {
                                        $message = 'undeleteviewlink';
index 6791503..2e7f065 100644 (file)
@@ -233,7 +233,10 @@ class LogEventsList extends ContextSource {
                foreach ( LogPage::validTypes() as $type ) {
                        $page = new LogPage( $type );
                        $restriction = $page->getRestriction();
-                       if ( $this->getUser()->isAllowed( $restriction ) ) {
+                       if ( MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), $restriction )
+                       ) {
                                $typesByName[$type] = $page->getName()->text();
                        }
                }
@@ -450,11 +453,12 @@ class LogEventsList extends ContextSource {
                }
 
                $del = '';
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
                // Don't show useless checkbox to people who cannot hide log entries
-               if ( $user->isAllowed( 'deletedhistory' ) ) {
-                       $canHide = $user->isAllowed( 'deletelogentry' );
-                       $canViewSuppressedOnly = $user->isAllowed( 'viewsuppressed' ) &&
-                               !$user->isAllowed( 'suppressrevision' );
+               if ( $permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
+                       $canHide = $permissionManager->userHasRight( $user, 'deletelogentry' );
+                       $canViewSuppressedOnly = $permissionManager->userHasRight( $user, 'viewsuppressed' ) &&
+                               !$permissionManager->userHasRight( $user, 'suppressrevision' );
                        $entryIsSuppressed = self::isDeleted( $row, LogPage::DELETED_RESTRICTED );
                        $canViewThisSuppressedEntry = $canViewSuppressedOnly && $entryIsSuppressed;
                        if ( $row->log_deleted || $canHide ) {
@@ -508,7 +512,9 @@ class LogEventsList extends ContextSource {
                                in_array( $row->log_action, $action ) : $row->log_action == $action;
                        if ( $match && $right ) {
                                global $wgUser;
-                               $match = $wgUser->isAllowed( $right );
+                               $match = MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $wgUser, $right );
                        }
                }
 
@@ -572,7 +578,10 @@ class LogEventsList extends ContextSource {
                        $user = $wgUser;
                }
                $logRestrictions = MediaWikiServices::getInstance()->getMainConfig()->get( 'LogRestrictions' );
-               if ( isset( $logRestrictions[$type] ) && !$user->isAllowed( $logRestrictions[$type] ) ) {
+               if ( isset( $logRestrictions[$type] ) && !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, $logRestrictions[$type] )
+               ) {
                        return false;
                }
                return true;
@@ -783,7 +792,10 @@ class LogEventsList extends ContextSource {
 
                // Don't show private logs to unprivileged users
                foreach ( $wgLogRestrictions as $logType => $right ) {
-                       if ( $audience == 'public' || !$user->isAllowed( $right ) ) {
+                       if ( $audience == 'public' || !MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $user, $right )
+                       ) {
                                $hiddenLogs[] = $logType;
                        }
                }
index 9e63ffe..b4a6825 100644 (file)
@@ -163,7 +163,9 @@ class LogFormatter {
                $logRestrictions = $this->context->getConfig()->get( 'LogRestrictions' );
                $type = $this->entry->getType();
                return !isset( $logRestrictions[$type] )
-                       || $this->context->getUser()->isAllowed( $logRestrictions[$type] );
+                       || MediaWikiServices::getInstance()
+                                  ->getPermissionManager()
+                                  ->userHasRight( $this->context->getUser(), $logRestrictions[$type] );
        }
 
        /**
index 3871047..5e9fdb8 100644 (file)
@@ -53,6 +53,12 @@ class LogPager extends ReverseChronologicalPager {
        /** @var bool */
        private $actionRestrictionsEnforced = false;
 
+       /** @var array */
+       private $mConds;
+
+       /** @var string */
+       private $mTagFilter;
+
        /** @var LogEventsList */
        public $mLogEventsList;
 
@@ -146,7 +152,9 @@ class LogPager extends ReverseChronologicalPager {
                $needReindex = false;
                foreach ( $types as $type ) {
                        if ( isset( $wgLogRestrictions[$type] )
-                               && !$user->isAllowed( $wgLogRestrictions[$type] )
+                               && !MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $user, $wgLogRestrictions[$type] )
                        ) {
                                $needReindex = true;
                                $types = array_diff( $types, [ $type ] );
@@ -462,12 +470,10 @@ class LogPager extends ReverseChronologicalPager {
                }
                $this->actionRestrictionsEnforced = true;
                $user = $this->getUser();
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( !$permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
                        $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::DELETED_ACTION ) . ' = 0';
-               } elseif ( !MediaWikiServices::getInstance()
-                       ->getPermissionManager()
-                       ->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' )
-               ) {
+               } elseif ( !$permissionManager->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' ) ) {
                        $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_ACTION ) .
                                ' != ' . LogPage::SUPPRESSED_USER;
                }
@@ -483,12 +489,10 @@ class LogPager extends ReverseChronologicalPager {
                }
                $this->performerRestrictionsEnforced = true;
                $user = $this->getUser();
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( !$permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
                        $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::DELETED_USER ) . ' = 0';
-               } elseif ( !MediaWikiServices::getInstance()
-                       ->getPermissionManager()
-                       ->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' )
-               ) {
+               } elseif ( !$permissionManager->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' ) ) {
                        $this->mConds[] = $this->mDb->bitAnd( 'log_deleted', LogPage::SUPPRESSED_USER ) .
                                ' != ' . LogPage::SUPPRESSED_ACTION;
                }
index 5326705..523a2f8 100644 (file)
@@ -253,8 +253,6 @@ class ManualLogEntry extends LogEntryBase implements Taggable {
         * @throws MWException
         */
        public function insert( IDatabase $dbw = null ) {
-               global $wgActorTableSchemaMigrationStage;
-
                $dbw = $dbw ?: wfGetDB( DB_MASTER );
 
                if ( $this->timestamp === null ) {
@@ -267,31 +265,6 @@ class ManualLogEntry extends LogEntryBase implements Taggable {
                $params = $this->getParameters();
                $relations = $this->relations;
 
-               // Ensure actor relations are set
-               if ( ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) &&
-                       empty( $relations['target_author_actor'] )
-               ) {
-                       $actorIds = [];
-                       if ( !empty( $relations['target_author_id'] ) ) {
-                               foreach ( $relations['target_author_id'] as $id ) {
-                                       $actorIds[] = User::newFromId( $id )->getActorId( $dbw );
-                               }
-                       }
-                       if ( !empty( $relations['target_author_ip'] ) ) {
-                               foreach ( $relations['target_author_ip'] as $ip ) {
-                                       $actorIds[] = User::newFromName( $ip, false )->getActorId( $dbw );
-                               }
-                       }
-                       if ( $actorIds ) {
-                               $relations['target_author_actor'] = $actorIds;
-                               $params['authorActors'] = $actorIds;
-                       }
-               }
-               if ( !( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) ) {
-                       unset( $relations['target_author_id'], $relations['target_author_ip'] );
-                       unset( $params['authorIds'], $params['authorIPs'] );
-               }
-
                // Additional fields for which there's no space in the database table schema
                $revId = $this->getAssociatedRevId();
                if ( $revId ) {
index 7a6fb9d..925c976 100644 (file)
@@ -22,6 +22,8 @@
  * @since 1.25
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This class formats merge log entries.
  *
@@ -47,7 +49,9 @@ class MergeLogFormatter extends LogFormatter {
 
        public function getActionLinks() {
                if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
-                       || !$this->context->getUser()->isAllowed( 'mergehistory' )
+                       || !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->context->getUser(), 'mergehistory' )
                ) {
                        return '';
                }
index 637a8e7..6797f98 100644 (file)
@@ -23,6 +23,8 @@
  * @since 1.22
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This class formats move log entries.
  *
@@ -60,7 +62,9 @@ class MoveLogFormatter extends LogFormatter {
        public function getActionLinks() {
                if ( $this->entry->isDeleted( LogPage::DELETED_ACTION ) // Action is hidden
                        || $this->entry->getSubtype() !== 'move'
-                       || !$this->context->getUser()->isAllowed( 'move' )
+                       || !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->context->getUser(), 'move' )
                ) {
                        return '';
                }
index ba02457..6e3b26b 100644 (file)
@@ -101,7 +101,10 @@ class ProtectLogFormatter extends LogFormatter {
                ];
 
                // Show change protection link
-               if ( $this->context->getUser()->isAllowed( 'protect' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->context->getUser(), 'protect' )
+               ) {
                        $links[] = $linkRenderer->makeKnownLink(
                                $title,
                                $this->msg( 'protect_change' )->text(),
index cba68ef..4d176fb 100644 (file)
@@ -129,7 +129,10 @@ class EmailNotification {
                if ( $watchers === [] && !count( $wgUsersNotifiedOnAllChanges ) ) {
                        $sendEmail = false;
                        // Only send notification for non minor edits, unless $wgEnotifMinorEdits
-                       if ( !$minorEdit || ( $wgEnotifMinorEdits && !$editor->isAllowed( 'nominornewtalk' ) ) ) {
+                       if ( !$minorEdit || ( $wgEnotifMinorEdits && !MediaWikiServices::getInstance()
+                                               ->getPermissionManager()
+                                               ->userHasRight( $editor, 'nominornewtalk' ) )
+                       ) {
                                $isUserTalkPage = ( $title->getNamespace() == NS_USER_TALK );
                                if ( $wgEnotifUserTalk
                                        && $isUserTalkPage
@@ -214,7 +217,10 @@ class EmailNotification {
 
                $userTalkId = false;
 
-               if ( !$minorEdit || ( $wgEnotifMinorEdits && !$editor->isAllowed( 'nominornewtalk' ) ) ) {
+               if ( !$minorEdit || ( $wgEnotifMinorEdits && !MediaWikiServices::getInstance()
+                                  ->getPermissionManager()
+                                  ->userHasRight( $editor, 'nominornewtalk' ) )
+               ) {
                        if ( $wgEnotifUserTalk
                                && $isUserTalkPage
                                && $this->canSendUserTalkEmail( $editor, $title, $minorEdit )
index 47fa16f..0783068 100644 (file)
@@ -34,8 +34,8 @@ class UserMailer {
         * Send mail using a PEAR mailer
         *
         * @param Mail_smtp $mailer
-        * @param string $dest
-        * @param string $headers
+        * @param string[]|string $dest
+        * @param array $headers
         * @param string $body
         *
         * @return Status
@@ -382,6 +382,8 @@ class UserMailer {
                                throw new MWException( 'PEAR mail package is not installed' );
                        }
 
+                       $recips = array_map( 'strval', $to );
+
                        Wikimedia\suppressWarnings();
 
                        // Create the mail object using the Mail::factory method
@@ -397,13 +399,13 @@ class UserMailer {
                        $headers['Subject'] = self::quotedPrintable( $subject );
 
                        // When sending only to one recipient, shows it its email using To:
-                       if ( count( $to ) == 1 ) {
-                               $headers['To'] = $to[0]->toString();
+                       if ( count( $recips ) == 1 ) {
+                               $headers['To'] = $recips[0];
                        }
 
                        // Split jobs since SMTP servers tends to limit the maximum
                        // number of possible recipients.
-                       $chunks = array_chunk( $to, $wgEnotifMaxRecips );
+                       $chunks = array_chunk( $recips, $wgEnotifMaxRecips );
                        foreach ( $chunks as $chunk ) {
                                $status = self::sendWithPear( $mail_object, $chunk, $headers, $body );
                                // FIXME : some chunks might be sent while others are not!
index 8a26f60..dffb1f9 100644 (file)
@@ -122,14 +122,17 @@ class JpegMetadataExtractor {
                                $temp = self::jpegExtractMarker( $fh );
                                // check what type of app segment this is.
                                if ( substr( $temp, 0, 29 ) === "http://ns.adobe.com/xap/1.0/\x00" && $showXMP ) {
-                                       $segments["XMP"] = substr( $temp, 29 );
+                                       // use trim to remove trailing \0 chars
+                                       $segments["XMP"] = trim( substr( $temp, 29 ) );
                                } elseif ( substr( $temp, 0, 35 ) === "http://ns.adobe.com/xmp/extension/\x00" && $showXMP ) {
-                                       $segments["XMP_ext"][] = substr( $temp, 35 );
+                                       // use trim to remove trailing \0 chars
+                                       $segments["XMP_ext"][] = trim( substr( $temp, 35 ) );
                                } elseif ( substr( $temp, 0, 29 ) === "XMP\x00://ns.adobe.com/xap/1.0/\x00" && $showXMP ) {
                                        // Some images (especially flickr images) seem to have this.
                                        // I really have no idea what the deal is with them, but
                                        // whatever...
-                                       $segments["XMP"] = substr( $temp, 29 );
+                                       // use trim to remove trailing \0 chars
+                                       $segments["XMP"] = trim( substr( $temp, 29 ) );
                                        wfDebug( __METHOD__ . ' Found XMP section with wrong app identifier '
                                                . "Using anyways.\n" );
                                } elseif ( substr( $temp, 0, 6 ) === "Exif\0\0" ) {
index 1c2e782..6aeb038 100644 (file)
@@ -363,8 +363,16 @@ class Article implements Page {
                        }
                }
 
+               $rl = MediaWikiServices::getInstance()->getRevisionLookup();
+               $oldRev = $this->mRevision ? $this->mRevision->getRevisionRecord() : null;
                if ( $request->getVal( 'direction' ) == 'next' ) {
-                       $nextid = $this->getTitle()->getNextRevisionID( $oldid );
+                       $nextid = 0;
+                       if ( $oldRev ) {
+                               $nextRev = $rl->getNextRevision( $oldRev );
+                               if ( $nextRev ) {
+                                       $nextid = $nextRev->getId();
+                               }
+                       }
                        if ( $nextid ) {
                                $oldid = $nextid;
                                $this->mRevision = null;
@@ -372,7 +380,13 @@ class Article implements Page {
                                $this->mRedirectUrl = $this->getTitle()->getFullURL( 'redirect=no' );
                        }
                } elseif ( $request->getVal( 'direction' ) == 'prev' ) {
-                       $previd = $this->getTitle()->getPreviousRevisionID( $oldid );
+                       $previd = 0;
+                       if ( $oldRev ) {
+                               $prevRev = $rl->getPreviousRevision( $oldRev );
+                               if ( $prevRev ) {
+                                       $previd = $prevRev->getId();
+                               }
+                       }
                        if ( $previd ) {
                                $oldid = $previd;
                                $this->mRevision = null;
@@ -1310,7 +1324,10 @@ class Article implements Page {
                }
 
                $outputPage->preventClickjacking();
-               if ( $user->isAllowed( 'writeapi' ) ) {
+               if ( MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'writeapi' )
+               ) {
                        $outputPage->addModules( 'mediawiki.page.patrol.ajax' );
                }
 
@@ -1596,8 +1613,9 @@ class Article implements Page {
                                        'oldid' => $oldid
                                ] + $extraParams
                        );
-               $prev = $this->getTitle()->getPreviousRevisionID( $oldid );
-               $prevlink = $prev
+               $rl = MediaWikiServices::getInstance()->getRevisionLookup();
+               $prevExist = (bool)$rl->getPreviousRevision( $revision->getRevisionRecord() );
+               $prevlink = $prevExist
                        ? Linker::linkKnown(
                                $this->getTitle(),
                                $context->msg( 'previousrevision' )->escaped(),
@@ -1608,7 +1626,7 @@ class Article implements Page {
                                ] + $extraParams
                        )
                        : $context->msg( 'previousrevision' )->escaped();
-               $prevdiff = $prev
+               $prevdiff = $prevExist
                        ? Linker::linkKnown(
                                $this->getTitle(),
                                $context->msg( 'diff' )->escaped(),
@@ -1827,7 +1845,10 @@ class Article implements Page {
                        [ 'delete', $this->getTitle()->getPrefixedText() ] )
                ) {
                        # Flag to hide all contents of the archived revisions
-                       $suppress = $request->getCheck( 'wpSuppress' ) && $user->isAllowed( 'suppressrevision' );
+
+                       $suppress = $request->getCheck( 'wpSuppress' ) && MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $user, 'suppressrevision' );
 
                        $this->doDelete( $reason, $suppress );
 
@@ -1986,8 +2007,8 @@ class Article implements Page {
                                ]
                        );
                }
-
-               if ( $user->isAllowed( 'suppressrevision' ) ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( $permissionManager->userHasRight( $user, 'suppressrevision' ) ) {
                        $fields[] = new OOUI\FieldLayout(
                                new OOUI\CheckboxInputWidget( [
                                        'name' => 'wpSuppress',
@@ -2045,7 +2066,7 @@ class Article implements Page {
                        ] )
                );
 
-               if ( $user->isAllowed( 'editinterface' ) ) {
+               if ( $permissionManager->userHasRight( $user, 'editinterface' ) ) {
                        $link = Linker::linkKnown(
                                $ctx->msg( 'deletereason-dropdown' )->inContentLanguage()->getTitle(),
                                wfMessage( 'delete-edit-reasonlist' )->escaped(),
index 9edaccc..cf2497f 100644 (file)
@@ -130,11 +130,10 @@ class ImageHistoryList extends ContextSource {
                $row = $selected = '';
 
                // Deletion link
-               if ( $local && ( $pm->userHasAnyRight( $user, 'delete', 'deletedhistory' ) )
-               ) {
+               if ( $local && ( $pm->userHasAnyRight( $user, 'delete', 'deletedhistory' ) ) ) {
                        $row .= '<td>';
                        # Link to remove from history
-                       if ( $user->isAllowed( 'delete' ) ) {
+                       if ( $pm->userHasRight( $user, 'delete' ) ) {
                                $q = [ 'action' => 'delete' ];
                                if ( !$iscur ) {
                                        $q['oldimage'] = $img;
@@ -146,9 +145,10 @@ class ImageHistoryList extends ContextSource {
                                );
                        }
                        # Link to hide content. Don't show useless link to people who cannot hide revisions.
-                       $canHide = $user->isAllowed( 'deleterevision' );
-                       if ( $canHide || ( $user->isAllowed( 'deletedhistory' ) && $file->getVisibility() ) ) {
-                               if ( $user->isAllowed( 'delete' ) ) {
+                       $canHide = $pm->userHasRight( $user, 'deleterevision' );
+                       if ( $canHide || ( $pm->userHasRight( $user, 'deletedhistory' )
+                                       && $file->getVisibility() ) ) {
+                               if ( $pm->userHasRight( $user, 'delete' ) ) {
                                        $row .= '<br />';
                                }
                                // If file is top revision or locked from this user, don't link
index 653e443..bb15532 100644 (file)
@@ -603,7 +603,10 @@ EOT
                                );
                        }
 
-                       if ( $wgEnableUploads && $user->isAllowed( 'upload' ) ) {
+                       if ( $wgEnableUploads && MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $user, 'upload' )
+                       ) {
                                // Only show an upload link if the user can upload
                                $uploadTitle = SpecialPage::getTitleFor( 'Upload' );
                                $nofile = [
index fea1bf6..f0a656d 100644 (file)
@@ -726,7 +726,7 @@ class WikiPage implements Page, IDBAccessObject {
                // Try using the replica DB first, then try the master
                $rev = $this->mTitle->getFirstRevision();
                if ( !$rev ) {
-                       $rev = $this->mTitle->getFirstRevision( Title::GAID_FOR_UPDATE );
+                       $rev = $this->mTitle->getFirstRevision( Title::READ_LATEST );
                }
                return $rev;
        }
@@ -1896,7 +1896,8 @@ class WikiPage implements Page, IDBAccessObject {
                // TODO: this check is here for backwards-compatibility with 1.31 behavior.
                // Checking the minoredit right should be done in the same place the 'bot' right is
                // checked for the EDIT_FORCE_BOT flag, which is currently in EditPage::attemptSave.
-               if ( ( $flags & EDIT_MINOR ) && !$user->isAllowed( 'minoredit' ) ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( ( $flags & EDIT_MINOR ) && !$permissionManager->userHasRight( $user, 'minoredit' ) ) {
                        $flags = ( $flags & ~EDIT_MINOR );
                }
 
@@ -1916,7 +1917,6 @@ class WikiPage implements Page, IDBAccessObject {
                // TODO: this logic should not be in the storage layer, it's here for compatibility
                // with 1.31 behavior. Applying the 'autopatrol' right should be done in the same
                // place the 'bot' right is handled, which is currently in EditPage::attemptSave.
-               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
 
                if ( $needsPatrol && $permissionManager->userCan(
                        'autopatrol', $user, $this->getTitle()
@@ -2841,7 +2841,7 @@ class WikiPage implements Page, IDBAccessObject {
         */
        protected function archiveRevisions( $dbw, $id, $suppress ) {
                global $wgContentHandlerUseDB, $wgMultiContentRevisionSchemaMigrationStage,
-                       $wgActorTableSchemaMigrationStage, $wgDeleteRevisionsBatchSize;
+                       $wgDeleteRevisionsBatchSize;
 
                // Given the lock above, we can be confident in the title and page ID values
                $namespace = $this->getTitle()->getNamespace();
@@ -2968,9 +2968,7 @@ class WikiPage implements Page, IDBAccessObject {
 
                        $dbw->delete( 'revision', [ 'rev_id' => $revids ], __METHOD__ );
                        $dbw->delete( 'revision_comment_temp', [ 'revcomment_rev' => $revids ], __METHOD__ );
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                               $dbw->delete( 'revision_actor_temp', [ 'revactor_rev' => $revids ], __METHOD__ );
-                       }
+                       $dbw->delete( 'revision_actor_temp', [ 'revactor_rev' => $revids ], __METHOD__ );
 
                        // Also delete records from ip_changes as applicable.
                        if ( count( $ipRevIds ) > 0 ) {
@@ -3251,14 +3249,12 @@ class WikiPage implements Page, IDBAccessObject {
                // Save
                $flags = EDIT_UPDATE | EDIT_INTERNAL;
 
-               if ( $guser->isAllowed( 'minoredit' ) ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( $permissionManager->userHasRight( $guser, 'minoredit' ) ) {
                        $flags |= EDIT_MINOR;
                }
 
-               if ( $bot && ( MediaWikiServices::getInstance()
-                               ->getPermissionManager()
-                               ->userHasAnyRight( $guser, 'markbotedits', 'bot' ) )
-               ) {
+               if ( $bot && ( $permissionManager->userHasAnyRight( $guser, 'markbotedits', 'bot' ) ) ) {
                        $flags |= EDIT_FORCE_BOT;
                }
 
@@ -3293,7 +3289,6 @@ class WikiPage implements Page, IDBAccessObject {
                // TODO: this logic should not be in the storage layer, it's here for compatibility
                // with 1.31 behavior. Applying the 'autopatrol' right should be done in the same
                // place the 'bot' right is handled, which is currently in EditPage::attemptSave.
-               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
 
                if ( $wgUseRCPatrol && $permissionManager->userCan(
                        'autopatrol', $guser, $this->getTitle()
@@ -3310,7 +3305,7 @@ class WikiPage implements Page, IDBAccessObject {
                // Set patrolling and bot flag on the edits, which gets rollbacked.
                // This is done even on edit failure to have patrolling in that case (T64157).
                $set = [];
-               if ( $bot && $guser->isAllowed( 'markbotedits' ) ) {
+               if ( $bot && $permissionManager->userHasRight( $guser, 'markbotedits' ) ) {
                        // Mark all reverted edits as bot
                        $set['rc_bot'] = 1;
                }
index b56527a..6b63a0d 100644 (file)
 
 /**
  * @ingroup Parser
+ *
+ * @property int $eqpos
+ * @property int $commentEnd
+ * @property int $visualEnd
  */
 class PPDPart {
        /**
index 68f1bb2..b9d796d 100644 (file)
@@ -27,6 +27,8 @@ class PPDStack {
        /** @var PPDStackElement[] */
        public $stack;
        public $rootAccum;
+       /** @var string|array */
+       public $accum;
 
        /**
         * @var PPDStackElement|false
index 116244d..fe2b04e 100644 (file)
@@ -21,6 +21,8 @@
 
 /**
  * @ingroup Parser
+ *
+ * @property int $startPos
  */
 class PPDStackElement {
        /**
index 3f147f0..b50fcfc 100644 (file)
@@ -21,6 +21,9 @@
 
 /**
  * @ingroup Parser
+ *
+ * @property int $depth
+ * @property PPFrame $parent
  */
 interface PPFrame {
        const NO_ARGS = 1;
index bb310f2..a0ec326 100644 (file)
@@ -82,7 +82,7 @@ class PPFrame_DOM implements PPFrame {
         * Create a new child frame
         * $args is optionally a multi-root PPNode or array containing the template arguments
         *
-        * @param bool|array $args
+        * @param bool|array|PPNode_DOM $args
         * @param Title|bool $title
         * @param int $indexOffset
         * @return PPTemplateFrame_DOM
@@ -95,11 +95,12 @@ class PPFrame_DOM implements PPFrame {
                }
                if ( $args !== false ) {
                        $xpath = false;
-                       if ( $args instanceof PPNode ) {
+                       if ( $args instanceof PPNode_DOM ) {
                                $args = $args->node;
                        }
+                       // @phan-suppress-next-line PhanTypeSuspiciousNonTraversableForeach
                        foreach ( $args as $arg ) {
-                               if ( $arg instanceof PPNode ) {
+                               if ( $arg instanceof PPNode_DOM ) {
                                        $arg = $arg->node;
                                }
                                if ( !$xpath || $xpath->document !== $arg->ownerDocument ) {
index df740cf..902e4f1 100644 (file)
@@ -40,6 +40,8 @@ class PPTemplateFrame_Hash extends PPFrame_Hash {
                $namedArgs = [], $title = false
        ) {
                parent::__construct( $preprocessor );
+               /** @var PPFrame_Hash parent */
+               '@phan-var PPFrame_Hash $parent';
 
                $this->parent = $parent;
                $this->numberedArgs = $numberedArgs;
index 99ca1be..19dd96e 100644 (file)
@@ -31,6 +31,11 @@ abstract class Preprocessor {
 
        const CACHE_VERSION = 1;
 
+       /**
+        * @var Parser
+        */
+       public $parser;
+
        /**
         * @var array Brace matching rules.
         */
index 9f4b7c7..7c372ee 100644 (file)
  */
 // phpcs:ignore Squiz.Classes.ValidClassName.NotCamelCaps
 class Preprocessor_Hash extends Preprocessor {
-
-       /**
-        * @var Parser
-        */
-       public $parser;
-
        const CACHE_PREFIX = 'preprocess-hash';
        const CACHE_VERSION = 2;
 
index 8a82add..56db812 100644 (file)
@@ -20,7 +20,6 @@
 
 namespace MediaWiki\Preferences;
 
-use Config;
 use DateTime;
 use DateTimeZone;
 use Exception;
@@ -37,6 +36,7 @@ use MediaWiki\Auth\PasswordAuthenticationRequest;
 use MediaWiki\Config\ServiceOptions;
 use MediaWiki\Linker\LinkRenderer;
 use MediaWiki\MediaWikiServices;
+use MediaWiki\Permissions\PermissionManager;
 use MessageLocalizer;
 use MWException;
 use MWTimestamp;
@@ -77,6 +77,9 @@ class DefaultPreferencesFactory implements PreferencesFactory {
        /** @var NamespaceInfo */
        protected $nsInfo;
 
+       /** @var PermissionManager */
+       protected $permissionManager;
+
        /**
         * TODO Make this a const when we drop HHVM support (T192166)
         *
@@ -84,6 +87,7 @@ class DefaultPreferencesFactory implements PreferencesFactory {
         * @since 1.34
         */
        public static $constructorOptions = [
+               'AllowRequiringEmailForResets',
                'AllowUserCss',
                'AllowUserCssPrefs',
                'AllowUserJs',
@@ -113,35 +117,34 @@ class DefaultPreferencesFactory implements PreferencesFactory {
        /**
         * Do not call this directly.  Get it from MediaWikiServices.
         *
-        * @param ServiceOptions|Config $options Config accepted for backwards compatibility
+        * @param ServiceOptions $options
         * @param Language $contLang
         * @param AuthManager $authManager
         * @param LinkRenderer $linkRenderer
-        * @param NamespaceInfo|null $nsInfo
+        * @param NamespaceInfo $nsInfo
+        * @param PermissionManager|null $permissionManager
         */
        public function __construct(
-               $options,
+               ServiceOptions $options,
                Language $contLang,
                AuthManager $authManager,
                LinkRenderer $linkRenderer,
-               NamespaceInfo $nsInfo = null
+               NamespaceInfo $nsInfo,
+               PermissionManager $permissionManager = null
        ) {
-               if ( $options instanceof Config ) {
-                       wfDeprecated( __METHOD__ . ' with Config parameter', '1.34' );
-                       $options = new ServiceOptions( self::$constructorOptions, $options );
-               }
-
                $options->assertRequiredOptions( self::$constructorOptions );
 
-               if ( !$nsInfo ) {
-                       wfDeprecated( __METHOD__ . ' with no NamespaceInfo argument', '1.34' );
-                       $nsInfo = MediaWikiServices::getInstance()->getNamespaceInfo();
+               if ( !$permissionManager ) {
+                       // TODO: this is actually hard-deprecated, left for jenkins to pass
+                       // together with GlobalPreferences extension. Will be removed in a followup.
+                       $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
                }
                $this->options = $options;
                $this->contLang = $contLang;
                $this->authManager = $authManager;
                $this->linkRenderer = $linkRenderer;
                $this->nsInfo = $nsInfo;
+               $this->permissionManager = $permissionManager;
                $this->logger = new NullLogger();
        }
 
@@ -208,7 +211,7 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                # # Make sure that form fields have their parent set. See T43337.
                $dummyForm = new HTMLForm( [], $context );
 
-               $disable = !$user->isAllowed( 'editmyoptions' );
+               $disable = !$this->permissionManager->userHasRight( $user, 'editmyoptions' );
 
                $defaultOptions = User::getDefaultOptions();
                $userOptions = $user->getOptions();
@@ -389,8 +392,8 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                        ];
                }
 
-               $canViewPrivateInfo = $user->isAllowed( 'viewmyprivateinfo' );
-               $canEditPrivateInfo = $user->isAllowed( 'editmyprivateinfo' );
+               $canViewPrivateInfo = $this->permissionManager->userHasRight( $user, 'viewmyprivateinfo' );
+               $canEditPrivateInfo = $this->permissionManager->userHasRight( $user, 'editmyprivateinfo' );
 
                // Actually changeable stuff
                $defaultPreferences['realname'] = [
@@ -620,7 +623,19 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                                }
                        }
 
-                       if ( $this->options->get( 'EnableUserEmail' ) && $user->isAllowed( 'sendemail' ) ) {
+                       if ( $this->options->get( 'AllowRequiringEmailForResets' ) ) {
+                               $defaultPreferences['requireemail'] = [
+                                       'type' => 'toggle',
+                                       'label-message' => 'tog-requireemail',
+                                       'help-message' => 'prefs-help-requireemail',
+                                       'section' => 'personal/email',
+                                       'disabled' => $disableEmailPrefs,
+                               ];
+                       }
+
+                       if ( $this->options->get( 'EnableUserEmail' ) &&
+                               $this->permissionManager->userHasRight( $user, 'sendemail' )
+                       ) {
                                $defaultPreferences['disablemail'] = [
                                        'id' => 'wpAllowEmail',
                                        'type' => 'toggle',
@@ -910,7 +925,7 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                        'label-message' => 'tog-numberheadings',
                ];
 
-               if ( $user->isAllowed( 'rollback' ) ) {
+               if ( $this->permissionManager->userHasRight( $user, 'rollback' ) ) {
                        $defaultPreferences['showrollbackconfirmation'] = [
                                'type' => 'toggle',
                                'section' => 'rendering/advancedrendering',
@@ -950,7 +965,7 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                        ];
                }
 
-               if ( $user->isAllowed( 'minoredit' ) ) {
+               if ( $this->permissionManager->userHasRight( $user, 'minoredit' ) ) {
                        $defaultPreferences['minordefault'] = [
                                'type' => 'toggle',
                                'section' => 'editing/editor',
@@ -1096,7 +1111,7 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                $watchlistdaysMax = ceil( $this->options->get( 'RCMaxAge' ) / ( 3600 * 24 ) );
 
                # # Watchlist #####################################
-               if ( $user->isAllowed( 'editmywatchlist' ) ) {
+               if ( $this->permissionManager->userHasRight( $user, 'editmywatchlist' ) ) {
                        $editWatchlistLinks = '';
                        $editWatchlistModes = [
                                'edit' => [ 'subpage' => false, 'flags' => [] ],
@@ -1210,20 +1225,20 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                ];
 
                // Kinda hacky
-               if ( $user->isAllowed( 'createpage' ) || $user->isAllowed( 'createtalk' ) ) {
+               if ( $this->permissionManager->userHasAnyRight( $user, 'createpage', 'createtalk' ) ) {
                        $watchTypes['read'] = 'watchcreations';
                }
 
-               if ( $user->isAllowed( 'rollback' ) ) {
+               if ( $this->permissionManager->userHasRight( $user, 'rollback' ) ) {
                        $watchTypes['rollback'] = 'watchrollback';
                }
 
-               if ( $user->isAllowed( 'upload' ) ) {
+               if ( $this->permissionManager->userHasRight( $user, 'upload' ) ) {
                        $watchTypes['upload'] = 'watchuploads';
                }
 
                foreach ( $watchTypes as $action => $pref ) {
-                       if ( $user->isAllowed( $action ) ) {
+                       if ( $this->permissionManager->userHasRight( $user, $action ) ) {
                                // Messages:
                                // tog-watchdefault, tog-watchmoves, tog-watchdeletion, tog-watchcreations, tog-watchuploads
                                // tog-watchrollback
@@ -1595,7 +1610,9 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                $hiddenPrefs = $this->options->get( 'HiddenPrefs' );
                $result = true;
 
-               if ( !$user->isAllowedAny( 'editmyprivateinfo', 'editmyoptions' ) ) {
+               if ( !$this->permissionManager
+                               ->userHasAnyRight( $user, 'editmyprivateinfo', 'editmyoptions' )
+               ) {
                        return Status::newFatal( 'mypreferencesprotected' );
                }
 
@@ -1606,14 +1623,14 @@ class DefaultPreferencesFactory implements PreferencesFactory {
                // (not really "private", but still shouldn't be edited without permission)
 
                if ( !in_array( 'realname', $hiddenPrefs )
-                       && $user->isAllowed( 'editmyprivateinfo' )
+                       && $this->permissionManager->userHasRight( $user, 'editmyprivateinfo' )
                        && array_key_exists( 'realname', $formData )
                ) {
                        $realName = $formData['realname'];
                        $user->setRealName( $realName );
                }
 
-               if ( $user->isAllowed( 'editmyoptions' ) ) {
+               if ( $this->permissionManager->userHasRight( $user, 'editmyoptions' ) ) {
                        $oldUserOptions = $user->getOptions();
 
                        foreach ( $this->getSaveBlacklist() as $b ) {
index 693afcf..6121bbf 100644 (file)
@@ -812,9 +812,9 @@ class ResourceLoader implements LoggerAwareInterface {
                        $errorText = implode( "\n\n", $this->errors );
                        $errorResponse = self::makeComment( $errorText );
                        if ( $context->shouldIncludeScripts() ) {
-                               $errorResponse .= 'if (window.console && console.error) {'
-                                       . Xml::encodeJsCall( 'console.error', [ $errorText ] )
-                                       . "}\n";
+                               $errorResponse .= 'if (window.console && console.error) { console.error('
+                                       . self::encodeJsonForScript( $errorText )
+                                       . "); }\n";
                        }
 
                        // Prepend error info to the response
@@ -1273,8 +1273,7 @@ MESSAGE;
        /**
         * Returns JS code which, when called, will register a given list of messages.
         *
-        * @param mixed $messages Either an associative array mapping message key to value, or a
-        *   JSON-encoded message blob containing the same data, wrapped in an XmlJsCode object.
+        * @param mixed $messages Associative array mapping message key to value.
         * @return string JavaScript code
         */
        public static function makeMessageSetScript( $messages ) {
@@ -1324,7 +1323,7 @@ MESSAGE;
         * @internal
         * @since 1.32
         * @param mixed $data
-        * @return string JSON
+        * @return string|false JSON string, false on error
         */
        public static function encodeJsonForScript( $data ) {
                // Keep output as small as possible by disabling needless escape modes
@@ -1545,20 +1544,16 @@ MESSAGE;
         * @throws Exception
         */
        public static function makeConfigSetScript( array $configuration ) {
-               $js = Xml::encodeJsCall(
-                       'mw.config.set',
-                       [ $configuration ],
-                       self::inDebugMode()
-               );
-               if ( $js === false ) {
+               $json = self::encodeJsonForScript( $configuration );
+               if ( $json === false ) {
                        $e = new Exception(
                                'JSON serialization of config data failed. ' .
                                'This usually means the config data is not valid UTF-8.'
                        );
                        MWExceptionHandler::logException( $e );
-                       $js = Xml::encodeJsCall( 'mw.log.error', [ $e->__toString() ] );
+                       return 'mw.log.error(' . self::encodeJsonForScript( $e->__toString() ) . ');';
                }
-               return $js;
+               return "mw.config.set($json);";
        }
 
        /**
index 151b5fd..ea35de6 100644 (file)
@@ -478,7 +478,7 @@ JAVASCRIPT;
                                                        ] );
                                                } else {
                                                        $chunk = ResourceLoader::makeInlineScript(
-                                                               Xml::encodeJsCall( 'mw.loader.load', [ $url ] ),
+                                                               'mw.loader.load(' . ResourceLoader::encodeJsonForScript( $url ) . ');',
                                                                $nonce
                                                        );
                                                }
index 7a7ab89..c0a0921 100644 (file)
@@ -52,16 +52,11 @@ class ResourceLoaderLanguageDataModule extends ResourceLoaderFileModule {
         * @return string JavaScript code
         */
        public function getScript( ResourceLoaderContext $context ) {
-               $fileScript = parent::getScript( $context );
-               $langDataScript = Xml::encodeJsCall(
-                       'mw.language.setData',
-                       [
-                               $context->getLanguage(),
-                               $this->getData( $context )
-                       ],
-                       ResourceLoader::inDebugMode()
-               );
-               return $fileScript . $langDataScript;
+               return parent::getScript( $context )
+                       . 'mw.language.setData('
+                       . ResourceLoader::encodeJsonForScript( $context->getLanguage() ) . ','
+                       . ResourceLoader::encodeJsonForScript( $this->getData( $context ) )
+                       . ');';
        }
 
        /**
index b9dc098..61cff82 100644 (file)
@@ -40,10 +40,8 @@ class ResourceLoaderUserDefaultsModule extends ResourceLoaderModule {
         * @return string JavaScript code
         */
        public function getScript( ResourceLoaderContext $context ) {
-               return Xml::encodeJsCall(
-                       'mw.user.options.set',
-                       [ User::getDefaultOptions() ],
-                       ResourceLoader::inDebugMode()
-               );
+               return 'mw.user.options.set('
+                       . ResourceLoader::encodeJsonForScript( User::getDefaultOptions() )
+                       . ');';
        }
 }
index 0d40ad7..ecbb501 100644 (file)
@@ -52,11 +52,12 @@ class ResourceLoaderUserOptionsModule extends ResourceLoaderModule {
         */
        public function getScript( ResourceLoaderContext $context ) {
                // Use FILTER_NOMIN annotation to prevent needless minification and caching (T84960).
-               return ResourceLoader::FILTER_NOMIN . Xml::encodeJsCall(
-                       'mw.user.options.set',
-                       [ $context->getUserObj()->getOptions( User::GETOPTIONS_EXCLUDE_DEFAULTS ) ],
-                       ResourceLoader::inDebugMode()
-               );
+               return ResourceLoader::FILTER_NOMIN
+                       . 'mw.user.options.set('
+                       . ResourceLoader::encodeJsonForScript(
+                               $context->getUserObj()->getOptions( User::GETOPTIONS_EXCLUDE_DEFAULTS )
+                       )
+                       . ');';
        }
 
        /**
index ae4fb67..85c14cb 100644 (file)
@@ -53,11 +53,10 @@ class ResourceLoaderUserTokensModule extends ResourceLoaderModule {
         */
        public function getScript( ResourceLoaderContext $context ) {
                // Use FILTER_NOMIN annotation to prevent needless minification and caching (T84960).
-               return ResourceLoader::FILTER_NOMIN . Xml::encodeJsCall(
-                       'mw.user.tokens.set',
-                       [ $this->contextUserTokens( $context ) ],
-                       ResourceLoader::inDebugMode()
-               );
+               return ResourceLoader::FILTER_NOMIN
+                       . 'mw.user.tokens.set('
+                       . ResourceLoader::encodeJsonForScript( $this->contextUserTokens( $context ) )
+                       . ');';
        }
 
        /**
index 74dd7bc..f4ea54f 100644 (file)
@@ -113,8 +113,6 @@ abstract class RevDelList extends RevisionListBase {
         * @since 1.23 Added 'perItemStatus' param
         */
        public function setVisibility( array $params ) {
-               global $wgActorTableSchemaMigrationStage;
-
                $status = Status::newGood();
 
                $bitPars = $params['value'];
@@ -143,7 +141,7 @@ abstract class RevDelList extends RevisionListBase {
                $missing = array_flip( $this->ids );
                $this->clearFileOps();
                $idsForLog = [];
-               $authorIds = $authorIPs = $authorActors = [];
+               $authorActors = [];
 
                if ( $perItemStatus ) {
                        $status->itemStatuses = [];
@@ -225,29 +223,7 @@ abstract class RevDelList extends RevisionListBase {
                                $virtualOldBits |= $removedBits;
 
                                $status->successCount++;
-                               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
-                                       if ( $item->getAuthorId() > 0 ) {
-                                               $authorIds[] = $item->getAuthorId();
-                                       } elseif ( IP::isIPAddress( $item->getAuthorName() ) ) {
-                                               $authorIPs[] = $item->getAuthorName();
-                                       }
-                                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                                               $actorId = $item->getAuthorActor();
-                                               // During migration, the actor field might be empty. If so, populate
-                                               // it here.
-                                               if ( !$actorId ) {
-                                                       if ( $item->getAuthorId() > 0 ) {
-                                                               $user = User::newFromId( $item->getAuthorId() );
-                                                       } else {
-                                                               $user = User::newFromName( $item->getAuthorName(), false );
-                                                       }
-                                                       $actorId = $user->getActorId( $dbw );
-                                               }
-                                               $authorActors[] = $actorId;
-                                       }
-                               } elseif ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                                       $authorActors[] = $item->getAuthorActor();
-                               }
+                               $authorActors[] = $item->getAuthorActor();
 
                                // Save the old and new bits in $visibilityChangeMap for
                                // later use.
@@ -291,13 +267,7 @@ abstract class RevDelList extends RevisionListBase {
 
                // Log it
                $authorFields = [];
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
-                       $authorFields['authorIds'] = $authorIds;
-                       $authorFields['authorIPs'] = $authorIPs;
-               }
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                       $authorFields['authorActors'] = $authorActors;
-               }
+               $authorFields['authorActors'] = $authorActors;
                $this->updateLog(
                        $logType,
                        [
@@ -363,8 +333,6 @@ abstract class RevDelList extends RevisionListBase {
         *     title:           The target title
         *     ids:             The ID list
         *     comment:         The log comment
-        *     authorIds:       The array of the user IDs of the offenders
-        *     authorIPs:       The array of the IP/anon user offenders
         *     authorActors:    The array of the actor IDs of the offenders
         *     tags:            The array of change tags to apply to the log entry
         * @throws MWException
@@ -387,12 +355,6 @@ abstract class RevDelList extends RevisionListBase {
                $relations = [
                        $field => $params['ids'],
                ];
-               if ( isset( $params['authorIds'] ) ) {
-                       $relations += [
-                               'target_author_id' => $params['authorIds'],
-                               'target_author_ip' => $params['authorIPs'],
-                       ];
-               }
                if ( isset( $params['authorActors'] ) ) {
                        $relations += [
                                'target_author_actor' => $params['authorActors'],
index 5644b95..9a9ab19 100644 (file)
@@ -44,8 +44,6 @@ class RevisionDeleteUser {
         * @return bool True on success, false on failure (e.g. invalid user ID)
         */
        private static function setUsernameBitfields( $name, $userId, $op, IDatabase $dbw = null ) {
-               global $wgActorTableSchemaMigrationStage;
-
                if ( !$userId || ( $op !== '|' && $op !== '&' ) ) {
                        return false; // sanity check
                }
@@ -69,19 +67,26 @@ class RevisionDeleteUser {
                $userTitle = Title::makeTitleSafe( NS_USER, $name );
                $userDbKey = $userTitle->getDBkey();
 
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
+               $actorId = $dbw->selectField( 'actor', 'actor_id', [ 'actor_name' => $name ], __METHOD__ );
+               if ( $actorId ) {
                        # Hide name from live edits
-                       $dbw->update(
-                               'revision',
-                               [ self::buildSetBitDeletedField( 'rev_deleted', $op, $delUser, $dbw ) ],
-                               [ 'rev_user' => $userId ],
-                               __METHOD__ );
+                       $ids = $dbw->selectFieldValues(
+                               'revision_actor_temp', 'revactor_rev', [ 'revactor_actor' => $actorId ], __METHOD__
+                       );
+                       if ( $ids ) {
+                               $dbw->update(
+                                       'revision',
+                                       [ self::buildSetBitDeletedField( 'rev_deleted', $op, $delUser, $dbw ) ],
+                                       [ 'rev_id' => $ids ],
+                                       __METHOD__
+                               );
+                       }
 
                        # Hide name from deleted edits
                        $dbw->update(
                                'archive',
                                [ self::buildSetBitDeletedField( 'ar_deleted', $op, $delUser, $dbw ) ],
-                               [ 'ar_user_text' => $name ],
+                               [ 'ar_actor' => $actorId ],
                                __METHOD__
                        );
 
@@ -89,7 +94,7 @@ class RevisionDeleteUser {
                        $dbw->update(
                                'logging',
                                [ self::buildSetBitDeletedField( 'log_deleted', $op, $delUser, $dbw ) ],
-                               [ 'log_user' => $userId, 'log_type != ' . $dbw->addQuotes( 'suppress' ) ],
+                               [ 'log_actor' => $actorId, 'log_type != ' . $dbw->addQuotes( 'suppress' ) ],
                                __METHOD__
                        );
 
@@ -97,7 +102,7 @@ class RevisionDeleteUser {
                        $dbw->update(
                                'recentchanges',
                                [ self::buildSetBitDeletedField( 'rc_deleted', $op, $delUser, $dbw ) ],
-                               [ 'rc_user_text' => $name ],
+                               [ 'rc_actor' => $actorId ],
                                __METHOD__
                        );
 
@@ -105,7 +110,7 @@ class RevisionDeleteUser {
                        $dbw->update(
                                'oldimage',
                                [ self::buildSetBitDeletedField( 'oi_deleted', $op, $delUser, $dbw ) ],
-                               [ 'oi_user_text' => $name ],
+                               [ 'oi_actor' => $actorId ],
                                __METHOD__
                        );
 
@@ -113,69 +118,11 @@ class RevisionDeleteUser {
                        $dbw->update(
                                'filearchive',
                                [ self::buildSetBitDeletedField( 'fa_deleted', $op, $delUser, $dbw ) ],
-                               [ 'fa_user_text' => $name ],
+                               [ 'fa_actor' => $actorId ],
                                __METHOD__
                        );
                }
 
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                       $actorId = $dbw->selectField( 'actor', 'actor_id', [ 'actor_name' => $name ], __METHOD__ );
-                       if ( $actorId ) {
-                               # Hide name from live edits
-                               $ids = $dbw->selectFieldValues(
-                                       'revision_actor_temp', 'revactor_rev', [ 'revactor_actor' => $actorId ], __METHOD__
-                               );
-                               if ( $ids ) {
-                                       $dbw->update(
-                                               'revision',
-                                               [ self::buildSetBitDeletedField( 'rev_deleted', $op, $delUser, $dbw ) ],
-                                               [ 'rev_id' => $ids ],
-                                               __METHOD__
-                                       );
-                               }
-
-                               # Hide name from deleted edits
-                               $dbw->update(
-                                       'archive',
-                                       [ self::buildSetBitDeletedField( 'ar_deleted', $op, $delUser, $dbw ) ],
-                                       [ 'ar_actor' => $actorId ],
-                                       __METHOD__
-                               );
-
-                               # Hide name from logs
-                               $dbw->update(
-                                       'logging',
-                                       [ self::buildSetBitDeletedField( 'log_deleted', $op, $delUser, $dbw ) ],
-                                       [ 'log_actor' => $actorId, 'log_type != ' . $dbw->addQuotes( 'suppress' ) ],
-                                       __METHOD__
-                               );
-
-                               # Hide name from RC
-                               $dbw->update(
-                                       'recentchanges',
-                                       [ self::buildSetBitDeletedField( 'rc_deleted', $op, $delUser, $dbw ) ],
-                                       [ 'rc_actor' => $actorId ],
-                                       __METHOD__
-                               );
-
-                               # Hide name from live images
-                               $dbw->update(
-                                       'oldimage',
-                                       [ self::buildSetBitDeletedField( 'oi_deleted', $op, $delUser, $dbw ) ],
-                                       [ 'oi_actor' => $actorId ],
-                                       __METHOD__
-                               );
-
-                               # Hide name from deleted images
-                               $dbw->update(
-                                       'filearchive',
-                                       [ self::buildSetBitDeletedField( 'fa_deleted', $op, $delUser, $dbw ) ],
-                                       [ 'fa_actor' => $actorId ],
-                                       __METHOD__
-                               );
-                       }
-               }
-
                # Hide log entries pointing to the user page
                $dbw->update(
                        'logging',
index 09cdf72..a3380ff 100644 (file)
@@ -505,11 +505,10 @@ final class SessionManager implements SessionManagerInterface {
                }
 
                if ( count( $retInfos ) > 1 ) {
-                       $ex = new \OverflowException(
+                       throw new SessionOverflowException(
+                               $retInfos,
                                'Multiple sessions for this request tied for top priority: ' . implode( ', ', $retInfos )
                        );
-                       $ex->sessionInfos = $retInfos;
-                       throw $ex;
                }
 
                return $retInfos ? $retInfos[0] : null;
diff --git a/includes/session/SessionOverflowException.php b/includes/session/SessionOverflowException.php
new file mode 100644 (file)
index 0000000..2a5ed2b
--- /dev/null
@@ -0,0 +1,34 @@
+<?php
+
+namespace MediaWiki\Session;
+
+/**
+ * OverflowException specific to the SessionManager, used when the request had multiple possible
+ * sessions tied for top priority.
+ *
+ * @since 1.34
+ */
+class SessionOverflowException extends \OverflowException {
+       /** @var SessionInfo[] */
+       private $sessionInfos;
+
+       /**
+        * @param SessionInfo[] $sessionInfos Must have at least two elements
+        * @param string $msg
+        * @throws \InvalidArgumentException If $sessionInfos has less than 2 elements
+        */
+       function __construct( array $sessionInfos, $msg ) {
+               if ( count( $sessionInfos ) < 2 ) {
+                       throw new \InvalidArgumentException( 'Expected at least two SessionInfo objects.' );
+               }
+               parent::__construct( $msg );
+               $this->sessionInfos = $sessionInfos;
+       }
+
+       /**
+        * @return SessionInfo[]
+        */
+       public function getSessionInfos() : array {
+               return $this->sessionInfos;
+       }
+}
index 70df73b..327061c 100644 (file)
@@ -595,7 +595,7 @@ class SkinTemplate extends Skin {
                # $this->getTitle() will just give Special:Badtitle, which is
                # not especially useful as a returnto parameter. Use the title
                # from the request instead, if there was one.
-               if ( $this->getUser()->isAllowed( 'read' ) ) {
+               if ( $permissionManager->userHasRight( $this->getUser(), 'read' ) ) {
                        $page = $this->getTitle();
                } else {
                        $page = Title::newFromText( $request->getVal( 'title', '' ) );
@@ -636,7 +636,7 @@ class SkinTemplate extends Skin {
                                'active' => ( $href == $pageurl )
                        ];
 
-                       if ( $this->getUser()->isAllowed( 'viewmywatchlist' ) ) {
+                       if ( $permissionManager->userHasRight( $this->getUser(), 'viewmywatchlist' ) ) {
                                $href = self::makeSpecialUrl( 'Watchlist' );
                                $personal_urls['watchlist'] = [
                                        'text' => $this->msg( 'mywatchlist' )->text(),
@@ -689,9 +689,8 @@ class SkinTemplate extends Skin {
                                $useCombinedLoginLink = false;
                        }
 
-                       $loginlink = $this->getUser()->isAllowed( 'createaccount' ) && $useCombinedLoginLink
-                               ? 'nav-login-createaccount'
-                               : 'pt-login';
+                       $loginlink = $permissionManager->userHasRight( $this->getUser(), 'createaccount' )
+                                                && $useCombinedLoginLink ? 'nav-login-createaccount' : 'pt-login';
 
                        $login_url = [
                                'text' => $this->msg( $loginlink )->text(),
@@ -727,7 +726,7 @@ class SkinTemplate extends Skin {
 
                        if (
                                $authManager->canCreateAccounts()
-                               && $this->getUser()->isAllowed( 'createaccount' )
+                               && $permissionManager->userHasRight( $this->getUser(), 'createaccount' )
                                && !$useCombinedLoginLink
                        ) {
                                $personal_urls['createaccount'] = $createaccount_url;
@@ -1074,8 +1073,7 @@ class SkinTemplate extends Skin {
 
                                if ( $permissionManager->quickUserCan( 'protect', $user, $title ) &&
                                         $title->getRestrictionTypes() &&
-                                        $permissionManager->getNamespaceRestrictionLevels( $title->getNamespace(),
-                                                $user ) !== [ '' ]
+                                        $permissionManager->getNamespaceRestrictionLevels( $title->getNamespace(), $user ) !== [ '' ]
                                ) {
                                        $mode = $title->isProtected() ? 'unprotect' : 'protect';
                                        $content_navigation['actions'][$mode] = [
@@ -1345,7 +1343,10 @@ class SkinTemplate extends Skin {
                                'href' => self::makeSpecialUrlSubpage( 'Log', $rootUser )
                        ];
 
-                       if ( $this->getUser()->isAllowed( 'block' ) ) {
+                       if ( MediawikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $this->getUser(), 'block' )
+                       ) {
                                $nav_urls['blockip'] = [
                                        'text' => $this->msg( 'blockip', $rootUser )->text(),
                                        'href' => self::makeSpecialUrlSubpage( 'Block', $rootUser )
index ce80c1a..94be852 100644 (file)
@@ -95,9 +95,8 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
 
        /**
         * Load basic request parameters for this Special page.
-        * @param string $subPage
         */
-       private function loadRequestParameters( $subPage ) {
+       private function loadRequestParameters() {
                if ( $this->mLoadedRequest ) {
                        return;
                }
@@ -105,7 +104,6 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                $request = $this->getRequest();
 
                $this->mPosted = $request->wasPosted();
-               $this->mIsReturn = $subPage === 'return';
                $this->mAction = $request->getVal( 'action' );
                $this->mFromHTTP = $request->getBool( 'fromhttp', false )
                        || $request->getBool( 'wpFromhttp', false );
@@ -124,7 +122,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
        protected function load( $subPage ) {
                global $wgSecureLogin;
 
-               $this->loadRequestParameters( $subPage );
+               $this->loadRequestParameters();
                if ( $this->mLoaded ) {
                        return;
                }
@@ -203,7 +201,7 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
 
        protected function beforeExecute( $subPage ) {
                // finish initializing the class before processing the request - T135924
-               $this->loadRequestParameters( $subPage );
+               $this->loadRequestParameters();
                return parent::beforeExecute( $subPage );
        }
 
@@ -977,7 +975,11 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
                        }
                }
                if ( !$this->isSignup() && $this->showExtraInformation() ) {
-                       $passwordReset = new PasswordReset( $this->getConfig(), AuthManager::singleton() );
+                       $passwordReset = new PasswordReset(
+                               $this->getConfig(),
+                               AuthManager::singleton(),
+                               MediaWikiServices::getInstance()->getPermissionManager()
+                       );
                        if ( $passwordReset->isAllowed( $this->getUser() )->isGood() ) {
                                $fieldDefinitions['passwordReset'] = [
                                        'type' => 'info',
@@ -1074,7 +1076,10 @@ abstract class LoginSignupSpecialPage extends AuthManagerSpecialPage {
        private function showCreateAccountLink() {
                if ( $this->isSignup() ) {
                        return true;
-               } elseif ( $this->getUser()->isAllowed( 'createaccount' ) ) {
+               } elseif ( MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $this->getUser(), 'createaccount' )
+               ) {
                        return true;
                } else {
                        return false;
index 6cc6e4e..b7eb3c0 100644 (file)
@@ -77,40 +77,40 @@ abstract class QueryPage extends SpecialPage {
                if ( $qp === null ) {
                        // QueryPage subclass, Special page name
                        $qp = [
-                               [ AncientPagesPage::class, 'Ancientpages' ],
-                               [ BrokenRedirectsPage::class, 'BrokenRedirects' ],
-                               [ DeadendPagesPage::class, 'Deadendpages' ],
-                               [ DoubleRedirectsPage::class, 'DoubleRedirects' ],
-                               [ FileDuplicateSearchPage::class, 'FileDuplicateSearch' ],
-                               [ ListDuplicatedFilesPage::class, 'ListDuplicatedFiles' ],
-                               [ LinkSearchPage::class, 'LinkSearch' ],
-                               [ ListredirectsPage::class, 'Listredirects' ],
-                               [ LonelyPagesPage::class, 'Lonelypages' ],
-                               [ LongPagesPage::class, 'Longpages' ],
-                               [ MediaStatisticsPage::class, 'MediaStatistics' ],
-                               [ MIMEsearchPage::class, 'MIMEsearch' ],
-                               [ MostcategoriesPage::class, 'Mostcategories' ],
+                               [ SpecialAncientPages::class, 'Ancientpages' ],
+                               [ SpecialBrokenRedirects::class, 'BrokenRedirects' ],
+                               [ SpecialDeadendPages::class, 'Deadendpages' ],
+                               [ SpecialDoubleRedirects::class, 'DoubleRedirects' ],
+                               [ SpecialFileDuplicateSearch::class, 'FileDuplicateSearch' ],
+                               [ SpecialListDuplicatedFiles::class, 'ListDuplicatedFiles' ],
+                               [ SpecialLinkSearch::class, 'LinkSearch' ],
+                               [ SpecialListRedirects::class, 'Listredirects' ],
+                               [ SpecialLonelyPages::class, 'Lonelypages' ],
+                               [ SpecialLongPages::class, 'Longpages' ],
+                               [ SpecialMediaStatistics::class, 'MediaStatistics' ],
+                               [ SpecialMIMESearch::class, 'MIMEsearch' ],
+                               [ SpecialMostCategories::class, 'Mostcategories' ],
                                [ MostimagesPage::class, 'Mostimages' ],
-                               [ MostinterwikisPage::class, 'Mostinterwikis' ],
-                               [ MostlinkedCategoriesPage::class, 'Mostlinkedcategories' ],
-                               [ MostlinkedTemplatesPage::class, 'Mostlinkedtemplates' ],
-                               [ MostlinkedPage::class, 'Mostlinked' ],
-                               [ MostrevisionsPage::class, 'Mostrevisions' ],
-                               [ FewestrevisionsPage::class, 'Fewestrevisions' ],
-                               [ ShortPagesPage::class, 'Shortpages' ],
-                               [ UncategorizedCategoriesPage::class, 'Uncategorizedcategories' ],
-                               [ UncategorizedPagesPage::class, 'Uncategorizedpages' ],
-                               [ UncategorizedImagesPage::class, 'Uncategorizedimages' ],
-                               [ UncategorizedTemplatesPage::class, 'Uncategorizedtemplates' ],
-                               [ UnusedCategoriesPage::class, 'Unusedcategories' ],
-                               [ UnusedimagesPage::class, 'Unusedimages' ],
-                               [ WantedCategoriesPage::class, 'Wantedcategories' ],
+                               [ SpecialMostInterwikis::class, 'Mostinterwikis' ],
+                               [ SpecialMostLinkedCategories::class, 'Mostlinkedcategories' ],
+                               [ SpecialMostLinkedTemplates::class, 'Mostlinkedtemplates' ],
+                               [ SpecialMostLinked::class, 'Mostlinked' ],
+                               [ SpecialMostRevisions::class, 'Mostrevisions' ],
+                               [ SpecialFewestRevisions::class, 'Fewestrevisions' ],
+                               [ SpecialShortPages::class, 'Shortpages' ],
+                               [ SpecialUncategorizedCategories::class, 'Uncategorizedcategories' ],
+                               [ SpecialUncategorizedPages::class, 'Uncategorizedpages' ],
+                               [ SpecialUncategorizedImages::class, 'Uncategorizedimages' ],
+                               [ SpecialUncategorizedTemplates::class, 'Uncategorizedtemplates' ],
+                               [ SpecialUnusedCategories::class, 'Unusedcategories' ],
+                               [ SpecialUnusedImages::class, 'Unusedimages' ],
+                               [ SpecialWantedCategories::class, 'Wantedcategories' ],
                                [ WantedFilesPage::class, 'Wantedfiles' ],
                                [ WantedPagesPage::class, 'Wantedpages' ],
-                               [ WantedTemplatesPage::class, 'Wantedtemplates' ],
-                               [ UnwatchedpagesPage::class, 'Unwatchedpages' ],
-                               [ UnusedtemplatesPage::class, 'Unusedtemplates' ],
-                               [ WithoutInterwikiPage::class, 'Withoutinterwiki' ],
+                               [ SpecialWantedTemplates::class, 'Wantedtemplates' ],
+                               [ SpecialUnwatchedPages::class, 'Unwatchedpages' ],
+                               [ SpecialUnusedTemplates::class, 'Unusedtemplates' ],
+                               [ SpecialWithoutInterwiki::class, 'Withoutinterwiki' ],
                        ];
                        Hooks::run( 'wgQueryPages', [ &$qp ] );
                }
index 7d33035..ba8e318 100644 (file)
@@ -292,7 +292,9 @@ class SpecialPage implements MessageLocalizer {
         * @return bool Does the user have permission to view the page?
         */
        public function userCanExecute( User $user ) {
-               return $user->isAllowed( $this->mRestriction );
+               return MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $user, $this->mRestriction );
        }
 
        /**
index 8134c9a..b83be91 100644 (file)
@@ -34,6 +34,7 @@ use RequestContext;
 use SpecialPage;
 use Title;
 use User;
+use Wikimedia\ObjectFactory;
 
 /**
  * Factory for handling the special page list and generating SpecialPage objects.
@@ -68,35 +69,35 @@ class SpecialPageFactory {
         */
        private static $coreList = [
                // Maintenance Reports
-               'BrokenRedirects' => \BrokenRedirectsPage::class,
-               'Deadendpages' => \DeadendPagesPage::class,
-               'DoubleRedirects' => \DoubleRedirectsPage::class,
-               'Longpages' => \LongPagesPage::class,
-               'Ancientpages' => \AncientPagesPage::class,
-               'Lonelypages' => \LonelyPagesPage::class,
-               'Fewestrevisions' => \FewestrevisionsPage::class,
-               'Withoutinterwiki' => \WithoutInterwikiPage::class,
+               'BrokenRedirects' => \SpecialBrokenRedirects::class,
+               'Deadendpages' => \SpecialDeadendPages::class,
+               'DoubleRedirects' => \SpecialDoubleRedirects::class,
+               'Longpages' => \SpecialLongPages::class,
+               'Ancientpages' => \SpecialAncientPages::class,
+               'Lonelypages' => \SpecialLonelyPages::class,
+               'Fewestrevisions' => \SpecialFewestRevisions::class,
+               'Withoutinterwiki' => \SpecialWithoutInterwiki::class,
                'Protectedpages' => \SpecialProtectedpages::class,
                'Protectedtitles' => \SpecialProtectedtitles::class,
-               'Shortpages' => \ShortPagesPage::class,
-               'Uncategorizedcategories' => \UncategorizedCategoriesPage::class,
-               'Uncategorizedimages' => \UncategorizedImagesPage::class,
-               'Uncategorizedpages' => \UncategorizedPagesPage::class,
-               'Uncategorizedtemplates' => \UncategorizedTemplatesPage::class,
-               'Unusedcategories' => \UnusedCategoriesPage::class,
-               'Unusedimages' => \UnusedimagesPage::class,
-               'Unusedtemplates' => \UnusedtemplatesPage::class,
-               'Unwatchedpages' => \UnwatchedpagesPage::class,
-               'Wantedcategories' => \WantedCategoriesPage::class,
+               'Shortpages' => \SpecialShortPages::class,
+               'Uncategorizedcategories' => \SpecialUncategorizedCategories::class,
+               'Uncategorizedimages' => \SpecialUncategorizedImages::class,
+               'Uncategorizedpages' => \SpecialUncategorizedPages::class,
+               'Uncategorizedtemplates' => \SpecialUncategorizedTemplates::class,
+               'Unusedcategories' => \SpecialUnusedCategories::class,
+               'Unusedimages' => \SpecialUnusedImages::class,
+               'Unusedtemplates' => \SpecialUnusedTemplates::class,
+               'Unwatchedpages' => \SpecialUnwatchedPages::class,
+               'Wantedcategories' => \SpecialWantedCategories::class,
                'Wantedfiles' => \WantedFilesPage::class,
                'Wantedpages' => \WantedPagesPage::class,
-               'Wantedtemplates' => \WantedTemplatesPage::class,
+               'Wantedtemplates' => \SpecialWantedTemplates::class,
 
                // List of pages
                'Allpages' => \SpecialAllPages::class,
                'Prefixindex' => \SpecialPrefixindex::class,
                'Categories' => \SpecialCategories::class,
-               'Listredirects' => \ListredirectsPage::class,
+               'Listredirects' => \SpecialListRedirects::class,
                'PagesWithProp' => \SpecialPagesWithProp::class,
                'TrackingCategories' => \SpecialTrackingCategories::class,
 
@@ -118,7 +119,7 @@ class SpecialPageFactory {
                'ChangePassword' => \SpecialChangePassword::class,
                'BotPasswords' => \SpecialBotPasswords::class,
                'PasswordReset' => \SpecialPasswordReset::class,
-               'DeletedContributions' => \DeletedContributionsPage::class,
+               'DeletedContributions' => \SpecialDeletedContributions::class,
                'Preferences' => \SpecialPreferences::class,
                'ResetTokens' => \SpecialResetTokens::class,
                'Contributions' => \SpecialContributions::class,
@@ -143,12 +144,12 @@ class SpecialPageFactory {
                // Media reports and uploads
                'Listfiles' => \SpecialListFiles::class,
                'Filepath' => \SpecialFilepath::class,
-               'MediaStatistics' => \MediaStatisticsPage::class,
-               'MIMEsearch' => \MIMEsearchPage::class,
-               'FileDuplicateSearch' => \FileDuplicateSearchPage::class,
+               'MediaStatistics' => \SpecialMediaStatistics::class,
+               'MIMEsearch' => \SpecialMIMESearch::class,
+               'FileDuplicateSearch' => \SpecialFileDuplicateSearch::class,
                'Upload' => \SpecialUpload::class,
                'UploadStash' => \SpecialUploadStash::class,
-               'ListDuplicatedFiles' => \ListDuplicatedFilesPage::class,
+               'ListDuplicatedFiles' => \SpecialListDuplicatedFiles::class,
 
                // Data and tools
                'ApiSandbox' => \SpecialApiSandbox::class,
@@ -159,7 +160,7 @@ class SpecialPageFactory {
                'Unlockdb' => \SpecialUnlockdb::class,
 
                // Redirecting special pages
-               'LinkSearch' => \LinkSearchPage::class,
+               'LinkSearch' => \SpecialLinkSearch::class,
                'Randompage' => \RandomPage::class,
                'RandomInCategory' => \SpecialRandomInCategory::class,
                'Randomredirect' => \SpecialRandomredirect::class,
@@ -167,13 +168,13 @@ class SpecialPageFactory {
                'GoToInterwiki' => \SpecialGoToInterwiki::class,
 
                // High use pages
-               'Mostlinkedcategories' => \MostlinkedCategoriesPage::class,
+               'Mostlinkedcategories' => \SpecialMostLinkedCategories::class,
                'Mostimages' => \MostimagesPage::class,
-               'Mostinterwikis' => \MostinterwikisPage::class,
-               'Mostlinked' => \MostlinkedPage::class,
-               'Mostlinkedtemplates' => \MostlinkedTemplatesPage::class,
-               'Mostcategories' => \MostcategoriesPage::class,
-               'Mostrevisions' => \MostrevisionsPage::class,
+               'Mostinterwikis' => \SpecialMostInterwikis::class,
+               'Mostlinked' => \SpecialMostLinked::class,
+               'Mostlinkedtemplates' => \SpecialMostLinkedTemplates::class,
+               'Mostcategories' => \SpecialMostCategories::class,
+               'Mostrevisions' => \SpecialMostRevisions::class,
 
                // Page tools
                'ComparePages' => \SpecialComparePages::class,
@@ -191,7 +192,12 @@ class SpecialPageFactory {
                'ApiHelp' => \SpecialApiHelp::class,
                'Blankpage' => \SpecialBlankpage::class,
                'Diff' => \SpecialDiff::class,
-               'EditTags' => \SpecialEditTags::class,
+               'EditTags' => [
+                       'class' => \SpecialEditTags::class,
+                       'services' => [
+                               'PermissionManager',
+                       ],
+               ],
                'Emailuser' => \SpecialEmailUser::class,
                'Movepage' => \MovePageForm::class,
                'Mycontributions' => \SpecialMycontributions::class,
@@ -203,7 +209,12 @@ class SpecialPageFactory {
                'NewSection' => \SpecialNewSection::class,
                'PermanentLink' => \SpecialPermanentLink::class,
                'Redirect' => \SpecialRedirect::class,
-               'Revisiondelete' => \SpecialRevisionDelete::class,
+               'Revisiondelete' => [
+                       'class' => \SpecialRevisionDelete::class,
+                       'services' => [
+                               'PermissionManager',
+                       ],
+               ],
                'RunJobs' => \SpecialRunJobs::class,
                'Specialpages' => \SpecialSpecialpages::class,
                'PageData' => \SpecialPageData::class,
@@ -221,6 +232,9 @@ class SpecialPageFactory {
        /** @var Language */
        private $contLang;
 
+       /** @var ObjectFactory */
+       private $objectFactory;
+
        /**
         * TODO Make this a const when HHVM support is dropped (T192166)
         *
@@ -241,11 +255,17 @@ class SpecialPageFactory {
        /**
         * @param ServiceOptions $options
         * @param Language $contLang
+        * @param ObjectFactory $objectFactory
         */
-       public function __construct( ServiceOptions $options, Language $contLang ) {
+       public function __construct(
+               ServiceOptions $options,
+               Language $contLang,
+               ObjectFactory $objectFactory
+       ) {
                $options->assertRequiredOptions( self::$constructorOptions );
                $this->options = $options;
                $this->contLang = $contLang;
+               $this->objectFactory = $objectFactory;
        }
 
        /**
@@ -272,8 +292,8 @@ class SpecialPageFactory {
                        }
 
                        if ( $this->options->get( 'EmailAuthentication' ) ) {
-                               $this->list['Confirmemail'] = \EmailConfirmation::class;
-                               $this->list['Invalidateemail'] = \EmailInvalidation::class;
+                               $this->list['Confirmemail'] = \SpecialConfirmEmail::class;
+                               $this->list['Invalidateemail'] = \SpecialEmailInvalidate::class;
                        }
 
                        if ( $this->options->get( 'EnableEmail' ) ) {
@@ -412,14 +432,22 @@ class SpecialPageFactory {
                if ( isset( $specialPageList[$realName] ) ) {
                        $rec = $specialPageList[$realName];
 
-                       if ( is_callable( $rec ) ) {
-                               // Use callback to instantiate the special page
-                               $page = $rec();
-                       } elseif ( is_string( $rec ) ) {
-                               $className = $rec;
-                               $page = new $className;
-                       } elseif ( $rec instanceof SpecialPage ) {
+                       if ( $rec instanceof SpecialPage ) {
+                               wfDeprecated(
+                                       "a SpecialPage instance (for $realName) in " .
+                                       '$wgSpecialPages or from the SpecialPage_initList hook',
+                                       '1.34'
+                               );
+
                                $page = $rec; // XXX: we should deep clone here
+                       } elseif ( is_array( $rec ) || is_string( $rec ) || is_callable( $rec ) ) {
+                               $page = $this->objectFactory->createObject(
+                                       $rec,
+                                       [
+                                               'allowClassName' => true,
+                                               'allowCallable' => true
+                                       ]
+                               );
                        } else {
                                $page = null;
                        }
diff --git a/includes/specials/SpecialAncientPages.php b/includes/specials/SpecialAncientPages.php
new file mode 100644 (file)
index 0000000..a17c121
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Implements Special:Ancientpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Implements Special:Ancientpages
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialAncientPages extends QueryPage {
+
+       function __construct( $name = 'Ancientpages' ) {
+               parent::__construct( $name );
+       }
+
+       public function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       public function getQueryInfo() {
+               $tables = [ 'page', 'revision' ];
+               $conds = [
+                       'page_namespace' =>
+                               MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces(),
+                       'page_is_redirect' => 0
+               ];
+               $joinConds = [
+                       'revision' => [
+                               'JOIN', [
+                                       'page_latest = rev_id'
+                               ]
+                       ],
+               ];
+
+               // Allow extensions to modify the query
+               Hooks::run( 'AncientPagesQuery', [ &$tables, &$conds, &$joinConds ] );
+
+               return [
+                       'tables' => $tables,
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'rev_timestamp'
+                       ],
+                       'conds' => $conds,
+                       'join_conds' => $joinConds
+               ];
+       }
+
+       public function usesTimestamps() {
+               return true;
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       public function preprocessResults( $db, $res ) {
+               $this->executeLBFromResultWrapper( $res );
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $d = $this->getLanguage()->userTimeAndDate( $result->value, $this->getUser() );
+               $title = Title::makeTitle( $result->namespace, $result->title );
+               $linkRenderer = $this->getLinkRenderer();
+               $link = $linkRenderer->makeKnownLink(
+                       $title,
+                       new HtmlArmor( MediaWikiServices::getInstance()->getContentLanguage()->
+                               convert( htmlspecialchars( $title->getPrefixedText() ) ) )
+               );
+
+               return $this->getLanguage()->specialList( $link, htmlspecialchars( $d ) );
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialAncientpages.php b/includes/specials/SpecialAncientpages.php
deleted file mode 100644 (file)
index a32393e..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-/**
- * Implements Special:Ancientpages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * Implements Special:Ancientpages
- *
- * @ingroup SpecialPage
- */
-class AncientPagesPage extends QueryPage {
-
-       function __construct( $name = 'Ancientpages' ) {
-               parent::__construct( $name );
-       }
-
-       public function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       public function getQueryInfo() {
-               $tables = [ 'page', 'revision' ];
-               $conds = [
-                       'page_namespace' =>
-                               MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces(),
-                       'page_is_redirect' => 0
-               ];
-               $joinConds = [
-                       'revision' => [
-                               'JOIN', [
-                                       'page_latest = rev_id'
-                               ]
-                       ],
-               ];
-
-               // Allow extensions to modify the query
-               Hooks::run( 'AncientPagesQuery', [ &$tables, &$conds, &$joinConds ] );
-
-               return [
-                       'tables' => $tables,
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'rev_timestamp'
-                       ],
-                       'conds' => $conds,
-                       'join_conds' => $joinConds
-               ];
-       }
-
-       public function usesTimestamps() {
-               return true;
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       public function preprocessResults( $db, $res ) {
-               $this->executeLBFromResultWrapper( $res );
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $d = $this->getLanguage()->userTimeAndDate( $result->value, $this->getUser() );
-               $title = Title::makeTitle( $result->namespace, $result->title );
-               $linkRenderer = $this->getLinkRenderer();
-               $link = $linkRenderer->makeKnownLink(
-                       $title,
-                       new HtmlArmor( MediaWikiServices::getInstance()->getContentLanguage()->
-                               convert( htmlspecialchars( $title->getPrefixedText() ) ) )
-               );
-
-               return $this->getLanguage()->specialList( $link, htmlspecialchars( $d ) );
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
index 9e49684..f4a33c8 100644 (file)
@@ -21,6 +21,8 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * @ingroup SpecialPage
  * @since 1.27
@@ -35,7 +37,10 @@ class SpecialApiSandbox extends SpecialPage {
                $out = $this->getOutput();
                $this->addHelpLink( 'Help:ApiSandbox' );
 
-               $out->addJsConfigVars( 'apihighlimits', $this->getUser()->isAllowed( 'apihighlimits' ) );
+               $out->addJsConfigVars( 'apihighlimits', MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $this->getUser(), 'apihighlimits' )
+               );
                $out->addModuleStyles( [
                        'mediawiki.special',
                        'mediawiki.hlist',
index 34c3371..3f98e93 100644 (file)
@@ -21,6 +21,8 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * A special page that lists autoblocks
  *
@@ -81,7 +83,10 @@ class SpecialAutoblockList extends SpecialPage {
                        'ipb_parent_block_id IS NOT NULL'
                ];
                # Is the user allowed to see hidden blocks?
-               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $this->getUser(), 'hideuser' )
+               ) {
                        $conds['ipb_deleted'] = 0;
                }
 
index 07214af..1b0db73 100644 (file)
@@ -25,6 +25,7 @@ use MediaWiki\Block\DatabaseBlock;
 use MediaWiki\Block\Restriction\PageRestriction;
 use MediaWiki\Block\Restriction\NamespaceRestriction;
 use MediaWiki\MediaWikiServices;
+use MediaWiki\User\UserIdentity;
 
 /**
  * A special page that allows users with 'block' right to block users from
@@ -269,7 +270,10 @@ class SpecialBlock extends FormSpecialPage {
                ];
 
                # Allow some users to hide name from block log, blocklist and listusers
-               if ( $user->isAllowed( 'hideuser' ) ) {
+               if ( MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $user, 'hideuser' )
+               ) {
                        $a['HideUser'] = [
                                'type' => 'check',
                                'label-message' => 'ipbhidename',
@@ -363,7 +367,10 @@ class SpecialBlock extends FormSpecialPage {
 
                        // If the username was hidden (ipb_deleted == 1), don't show the reason
                        // unless this user also has rights to hideuser: T37839
-                       if ( !$block->getHideName() || $this->getUser()->isAllowed( 'hideuser' ) ) {
+                       if ( !$block->getHideName() || MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $this->getUser(), 'hideuser' )
+                       ) {
                                $fields['Reason']['default'] = $block->getReason();
                        } else {
                                $fields['Reason']['default'] = '';
@@ -545,7 +552,8 @@ class SpecialBlock extends FormSpecialPage {
                $user = $this->getUser();
 
                # Link to edit the block dropdown reasons, if applicable
-               if ( $user->isAllowed( 'editinterface' ) ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( $permissionManager->userHasRight( $user, 'editinterface' ) ) {
                        $links[] = $linkRenderer->makeKnownLink(
                                $this->msg( 'ipbreason-dropdown' )->inContentLanguage()->getTitle(),
                                $this->msg( 'ipb-edit-dropdown' )->text(),
@@ -579,7 +587,7 @@ class SpecialBlock extends FormSpecialPage {
                        $text .= $out;
 
                        # Add suppression block entries if allowed
-                       if ( $user->isAllowed( 'suppressionlog' ) ) {
+                       if ( $permissionManager->userHasRight( $user, 'suppressionlog' ) ) {
                                LogEventsList::showLogExtract(
                                        $out,
                                        'suppress',
@@ -828,7 +836,10 @@ class SpecialBlock extends FormSpecialPage {
                }
 
                if ( $data['HideUser'] ) {
-                       if ( !$performer->isAllowed( 'hideuser' ) ) {
+                       if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $performer, 'hideuser' )
+                       ) {
                                # this codepath is unreachable except by a malicious user spoofing forms,
                                # or by race conditions (user has hideuser and block rights, loads block form,
                                # and loses hideuser rights before submission); so need to fail completely
@@ -938,7 +949,10 @@ class SpecialBlock extends FormSpecialPage {
                                }
                                # If the name was hidden and the blocking user cannot hide
                                # names, then don't allow any block changes...
-                               if ( $currentBlock->getHideName() && !$performer->isAllowed( 'hideuser' ) ) {
+                               if ( $currentBlock->getHideName() && !MediaWikiServices::getInstance()
+                                               ->getPermissionManager()
+                                               ->userHasRight( $performer, 'hideuser' )
+                               ) {
                                        return [ 'cant-see-hidden-user' ];
                                }
 
@@ -1106,13 +1120,15 @@ class SpecialBlock extends FormSpecialPage {
 
        /**
         * Can we do an email block?
-        * @param User $user The sysop wanting to make a block
+        * @param UserIdentity $user The sysop wanting to make a block
         * @return bool
         */
-       public static function canBlockEmail( $user ) {
+       public static function canBlockEmail( UserIdentity $user ) {
                global $wgEnableUserEmail, $wgSysopEmailBans;
 
-               return ( $wgEnableUserEmail && $wgSysopEmailBans && $user->isAllowed( 'blockemail' ) );
+               return ( $wgEnableUserEmail && $wgSysopEmailBans && MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'blockemail' ) );
        }
 
        /**
@@ -1138,7 +1154,10 @@ class SpecialBlock extends FormSpecialPage {
                if ( $performer->getBlock() ) {
                        if ( $target instanceof User && $target->getId() == $performer->getId() ) {
                                # User is trying to unblock themselves
-                               if ( $performer->isAllowed( 'unblockself' ) ) {
+                               if ( MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $performer, 'unblockself' )
+                               ) {
                                        return true;
                                        # User blocked themselves and is now trying to reverse it
                                } elseif ( $performer->blockedBy() === $performer->getName() ) {
index b3d2358..2dd682f 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 use MediaWiki\Block\DatabaseBlock;
+use MediaWiki\MediaWikiServices;
 
 /**
  * A special page that lists existing blocks
@@ -82,8 +83,9 @@ class SpecialBlockList extends SpecialPage {
                        'Options' => [
                                'type' => 'multiselect',
                                'options-messages' => [
-                                       'blocklist-userblocks' => 'userblocks',
                                        'blocklist-tempblocks' => 'tempblocks',
+                                       'blocklist-indefblocks' => 'indefblocks',
+                                       'blocklist-userblocks' => 'userblocks',
                                        'blocklist-addressblocks' => 'addressblocks',
                                        'blocklist-rangeblocks' => 'rangeblocks',
                                ],
@@ -136,8 +138,12 @@ class SpecialBlockList extends SpecialPage {
         */
        protected function getBlockListPager() {
                $conds = [];
+               $db = $this->getDB();
                # Is the user allowed to see hidden blocks?
-               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $this->getUser(), 'hideuser' )
+               ) {
                        $conds['ipb_deleted'] = 0;
                }
 
@@ -153,7 +159,7 @@ class SpecialBlockList extends SpecialPage {
                                case DatabaseBlock::TYPE_IP:
                                case DatabaseBlock::TYPE_RANGE:
                                        list( $start, $end ) = IP::parseRange( $target );
-                                       $conds[] = wfGetDB( DB_REPLICA )->makeList(
+                                       $conds[] = $db->makeList(
                                                [
                                                        'ipb_address' => $target,
                                                        DatabaseBlock::getRangeCond( $start, $end )
@@ -174,9 +180,6 @@ class SpecialBlockList extends SpecialPage {
                if ( in_array( 'userblocks', $this->options ) ) {
                        $conds['ipb_user'] = 0;
                }
-               if ( in_array( 'tempblocks', $this->options ) ) {
-                       $conds['ipb_expiry'] = 'infinity';
-               }
                if ( in_array( 'addressblocks', $this->options ) ) {
                        $conds[] = "ipb_user != 0 OR ipb_range_end > ipb_range_start";
                }
@@ -184,10 +187,21 @@ class SpecialBlockList extends SpecialPage {
                        $conds[] = "ipb_range_end = ipb_range_start";
                }
 
+               $hideTemp = in_array( 'tempblocks', $this->options );
+               $hideIndef = in_array( 'indefblocks', $this->options );
+               if ( $hideTemp && $hideIndef ) {
+                       // If both types are hidden, ensure query doesn't produce any results
+                       $conds[] = '1=0';
+               } elseif ( $hideTemp ) {
+                       $conds['ipb_expiry'] = $db->getInfinity();
+               } elseif ( $hideIndef ) {
+                       $conds[] = "ipb_expiry != " . $db->addQuotes( $db->getInfinity() );
+               }
+
                if ( $this->blockType === 'sitewide' ) {
-                       $conds[] = 'ipb_sitewide = 1';
+                       $conds['ipb_sitewide'] = 1;
                } elseif ( $this->blockType === 'partial' ) {
-                       $conds[] = 'ipb_sitewide = 0';
+                       $conds['ipb_sitewide'] = 0;
                }
 
                return new BlockListPager( $this, $conds );
@@ -243,4 +257,13 @@ class SpecialBlockList extends SpecialPage {
        protected function getGroupName() {
                return 'users';
        }
+
+       /**
+        * Return a IDatabase object for reading
+        *
+        * @return IDatabase
+        */
+       protected function getDB() {
+               return wfGetDB( DB_REPLICA );
+       }
 }
index 17f89f9..392b4e9 100644 (file)
@@ -21,6 +21,7 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\Rdbms\IResultWrapper;
 use Wikimedia\Rdbms\IDatabase;
 
@@ -30,7 +31,7 @@ use Wikimedia\Rdbms\IDatabase;
  *
  * @ingroup SpecialPage
  */
-class BrokenRedirectsPage extends QueryPage {
+class SpecialBrokenRedirects extends QueryPage {
        function __construct( $name = 'BrokenRedirects' ) {
                parent::__construct( $name );
        }
@@ -114,6 +115,8 @@ class BrokenRedirectsPage extends QueryPage {
                }
 
                $linkRenderer = $this->getLinkRenderer();
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+
                // $toObj may very easily be false if the $result list is cached
                if ( !is_object( $toObj ) ) {
                        return '<del>' . $linkRenderer->makeLink( $fromObj ) . '</del>';
@@ -129,7 +132,7 @@ class BrokenRedirectsPage extends QueryPage {
                // if the page is editable, add an edit link
                if (
                        // check user permissions
-                       $this->getUser()->isAllowed( 'edit' ) &&
+                       $permissionManager->userHasRight( $this->getUser(), 'edit' ) &&
                        // check, if the content model is editable through action=edit
                        ContentHandler::getForTitle( $fromObj )->supportsDirectEditing()
                ) {
@@ -145,7 +148,7 @@ class BrokenRedirectsPage extends QueryPage {
 
                $out = $from . $this->msg( 'word-separator' )->escaped();
 
-               if ( $this->getUser()->isAllowed( 'delete' ) ) {
+               if ( $permissionManager->userHasRight( $this->getUser(), 'delete' ) ) {
                        $links[] = $linkRenderer->makeKnownLink(
                                $fromObj,
                                $this->msg( 'brokenredirects-delete' )->text(),
index 01f7e56..46fa17e 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
+
 class SpecialChangeContentModel extends FormSpecialPage {
 
        public function __construct() {
@@ -226,7 +228,10 @@ class SpecialChangeContentModel extends FormSpecialPage {
 
                $flags = $this->oldRevision ? EDIT_UPDATE : EDIT_NEW;
                $flags |= EDIT_INTERNAL;
-               if ( $user->isAllowed( 'bot' ) ) {
+               if ( MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'bot' )
+               ) {
                        $flags |= EDIT_FORCE_BOT;
                }
 
index c95aa1b..7331cd7 100644 (file)
@@ -23,6 +23,7 @@
 
 use MediaWiki\Auth\AuthManager;
 use MediaWiki\Logger\LoggerFactory;
+use MediaWiki\MediaWikiServices;
 
 /**
  * Let users change their email address.
@@ -74,7 +75,10 @@ class SpecialChangeEmail extends FormSpecialPage {
 
                // This could also let someone check the current email address, so
                // require both permissions.
-               if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'viewmyprivateinfo' )
+               ) {
                        throw new PermissionsError( 'viewmyprivateinfo' );
                }
 
diff --git a/includes/specials/SpecialConfirmEmail.php b/includes/specials/SpecialConfirmEmail.php
new file mode 100644 (file)
index 0000000..2c42cd3
--- /dev/null
@@ -0,0 +1,180 @@
+<?php
+/**
+ * Implements Special:Confirmemail
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Special page allows users to request email confirmation message, and handles
+ * processing of the confirmation code when the link in the email is followed
+ *
+ * @ingroup SpecialPage
+ * @author Brion Vibber
+ * @author Rob Church <robchur@gmail.com>
+ */
+class SpecialConfirmEmail extends UnlistedSpecialPage {
+       public function __construct() {
+               parent::__construct( 'Confirmemail', 'editmyprivateinfo' );
+       }
+
+       public function doesWrites() {
+               return true;
+       }
+
+       /**
+        * Main execution point
+        *
+        * @param null|string $code Confirmation code passed to the page
+        * @throws PermissionsError
+        * @throws ReadOnlyError
+        * @throws UserNotLoggedIn
+        */
+       function execute( $code ) {
+               // Ignore things like master queries/connections on GET requests.
+               // It's very convenient to just allow formless link usage.
+               $trxProfiler = Profiler::instance()->getTransactionProfiler();
+
+               $this->setHeaders();
+               $this->checkReadOnly();
+               $this->checkPermissions();
+
+               // This could also let someone check the current email address, so
+               // require both permissions.
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'viewmyprivateinfo' )
+               ) {
+                       throw new PermissionsError( 'viewmyprivateinfo' );
+               }
+
+               if ( $code === null || $code === '' ) {
+                       $this->requireLogin( 'confirmemail_needlogin' );
+                       if ( Sanitizer::validateEmail( $this->getUser()->getEmail() ) ) {
+                               $this->showRequestForm();
+                       } else {
+                               $this->getOutput()->addWikiMsg( 'confirmemail_noemail' );
+                       }
+               } else {
+                       $old = $trxProfiler->setSilenced( true );
+                       $this->attemptConfirm( $code );
+                       $trxProfiler->setSilenced( $old );
+               }
+       }
+
+       /**
+        * Show a nice form for the user to request a confirmation mail
+        */
+       function showRequestForm() {
+               $user = $this->getUser();
+               $out = $this->getOutput();
+
+               if ( !$user->isEmailConfirmed() ) {
+                       $descriptor = [];
+                       if ( $user->isEmailConfirmationPending() ) {
+                               $descriptor += [
+                                       'pending' => [
+                                               'type' => 'info',
+                                               'raw' => true,
+                                               'default' => "<div class=\"error mw-confirmemail-pending\">\n" .
+                                                       $this->msg( 'confirmemail_pending' )->escaped() .
+                                                       "\n</div>",
+                                       ],
+                               ];
+                       }
+
+                       $out->addWikiMsg( 'confirmemail_text' );
+                       $form = HTMLForm::factory( 'ooui', $descriptor, $this->getContext() );
+                       $form
+                               ->setMethod( 'post' )
+                               ->setAction( $this->getPageTitle()->getLocalURL() )
+                               ->setSubmitTextMsg( 'confirmemail_send' )
+                               ->setSubmitCallback( [ $this, 'submitSend' ] );
+
+                       $retval = $form->show();
+
+                       if ( $retval === true ) {
+                               // should never happen, but if so, don't let the user without any message
+                               $out->addWikiMsg( 'confirmemail_sent' );
+                       } elseif ( $retval instanceof Status && $retval->isGood() ) {
+                               $out->addWikiTextAsInterface( $retval->getValue() );
+                       }
+               } else {
+                       // date and time are separate parameters to facilitate localisation.
+                       // $time is kept for backward compat reasons.
+                       // 'emailauthenticated' is also used in SpecialPreferences.php
+                       $lang = $this->getLanguage();
+                       $emailAuthenticated = $user->getEmailAuthenticationTimestamp();
+                       $time = $lang->userTimeAndDate( $emailAuthenticated, $user );
+                       $d = $lang->userDate( $emailAuthenticated, $user );
+                       $t = $lang->userTime( $emailAuthenticated, $user );
+                       $out->addWikiMsg( 'emailauthenticated', $time, $d, $t );
+               }
+       }
+
+       /**
+        * Callback for HTMLForm send confirmation mail.
+        *
+        * @return Status Status object with the result
+        */
+       public function submitSend() {
+               $status = $this->getUser()->sendConfirmationMail();
+               if ( $status->isGood() ) {
+                       return Status::newGood( $this->msg( 'confirmemail_sent' )->text() );
+               } else {
+                       return Status::newFatal( new RawMessage(
+                               $status->getWikiText( 'confirmemail_sendfailed' )
+                       ) );
+               }
+       }
+
+       /**
+        * Attempt to confirm the user's email address and show success or failure
+        * as needed; if successful, take the user to log in
+        *
+        * @param string $code Confirmation code
+        */
+       private function attemptConfirm( $code ) {
+               $user = User::newFromConfirmationCode( $code, User::READ_EXCLUSIVE );
+               if ( !is_object( $user ) ) {
+                       $this->getOutput()->addWikiMsg( 'confirmemail_invalid' );
+
+                       return;
+               }
+
+               // rate limit email confirmations
+               if ( $user->pingLimiter( 'confirmemail' ) ) {
+                       $this->getOutput()->addWikiMsg( 'actionthrottledtext' );
+
+                       return;
+               }
+
+               $user->confirmEmail();
+               $user->saveSettings();
+               $message = $this->getUser()->isLoggedIn() ? 'confirmemail_loggedin' : 'confirmemail_success';
+               $this->getOutput()->addWikiMsg( $message );
+
+               if ( !$this->getUser()->isLoggedIn() ) {
+                       $title = SpecialPage::getTitleFor( 'Userlogin' );
+                       $this->getOutput()->returnToMain( true, $title );
+               }
+       }
+}
diff --git a/includes/specials/SpecialConfirmemail.php b/includes/specials/SpecialConfirmemail.php
deleted file mode 100644 (file)
index 7f32719..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-<?php
-/**
- * Implements Special:Confirmemail
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-/**
- * Special page allows users to request email confirmation message, and handles
- * processing of the confirmation code when the link in the email is followed
- *
- * @ingroup SpecialPage
- * @author Brion Vibber
- * @author Rob Church <robchur@gmail.com>
- */
-class EmailConfirmation extends UnlistedSpecialPage {
-       public function __construct() {
-               parent::__construct( 'Confirmemail', 'editmyprivateinfo' );
-       }
-
-       public function doesWrites() {
-               return true;
-       }
-
-       /**
-        * Main execution point
-        *
-        * @param null|string $code Confirmation code passed to the page
-        * @throws PermissionsError
-        * @throws ReadOnlyError
-        * @throws UserNotLoggedIn
-        */
-       function execute( $code ) {
-               // Ignore things like master queries/connections on GET requests.
-               // It's very convenient to just allow formless link usage.
-               $trxProfiler = Profiler::instance()->getTransactionProfiler();
-
-               $this->setHeaders();
-               $this->checkReadOnly();
-               $this->checkPermissions();
-
-               // This could also let someone check the current email address, so
-               // require both permissions.
-               if ( !$this->getUser()->isAllowed( 'viewmyprivateinfo' ) ) {
-                       throw new PermissionsError( 'viewmyprivateinfo' );
-               }
-
-               if ( $code === null || $code === '' ) {
-                       $this->requireLogin( 'confirmemail_needlogin' );
-                       if ( Sanitizer::validateEmail( $this->getUser()->getEmail() ) ) {
-                               $this->showRequestForm();
-                       } else {
-                               $this->getOutput()->addWikiMsg( 'confirmemail_noemail' );
-                       }
-               } else {
-                       $old = $trxProfiler->setSilenced( true );
-                       $this->attemptConfirm( $code );
-                       $trxProfiler->setSilenced( $old );
-               }
-       }
-
-       /**
-        * Show a nice form for the user to request a confirmation mail
-        */
-       function showRequestForm() {
-               $user = $this->getUser();
-               $out = $this->getOutput();
-
-               if ( !$user->isEmailConfirmed() ) {
-                       $descriptor = [];
-                       if ( $user->isEmailConfirmationPending() ) {
-                               $descriptor += [
-                                       'pending' => [
-                                               'type' => 'info',
-                                               'raw' => true,
-                                               'default' => "<div class=\"error mw-confirmemail-pending\">\n" .
-                                                       $this->msg( 'confirmemail_pending' )->escaped() .
-                                                       "\n</div>",
-                                       ],
-                               ];
-                       }
-
-                       $out->addWikiMsg( 'confirmemail_text' );
-                       $form = HTMLForm::factory( 'ooui', $descriptor, $this->getContext() );
-                       $form
-                               ->setMethod( 'post' )
-                               ->setAction( $this->getPageTitle()->getLocalURL() )
-                               ->setSubmitTextMsg( 'confirmemail_send' )
-                               ->setSubmitCallback( [ $this, 'submitSend' ] );
-
-                       $retval = $form->show();
-
-                       if ( $retval === true ) {
-                               // should never happen, but if so, don't let the user without any message
-                               $out->addWikiMsg( 'confirmemail_sent' );
-                       } elseif ( $retval instanceof Status && $retval->isGood() ) {
-                               $out->addWikiTextAsInterface( $retval->getValue() );
-                       }
-               } else {
-                       // date and time are separate parameters to facilitate localisation.
-                       // $time is kept for backward compat reasons.
-                       // 'emailauthenticated' is also used in SpecialPreferences.php
-                       $lang = $this->getLanguage();
-                       $emailAuthenticated = $user->getEmailAuthenticationTimestamp();
-                       $time = $lang->userTimeAndDate( $emailAuthenticated, $user );
-                       $d = $lang->userDate( $emailAuthenticated, $user );
-                       $t = $lang->userTime( $emailAuthenticated, $user );
-                       $out->addWikiMsg( 'emailauthenticated', $time, $d, $t );
-               }
-       }
-
-       /**
-        * Callback for HTMLForm send confirmation mail.
-        *
-        * @return Status Status object with the result
-        */
-       public function submitSend() {
-               $status = $this->getUser()->sendConfirmationMail();
-               if ( $status->isGood() ) {
-                       return Status::newGood( $this->msg( 'confirmemail_sent' )->text() );
-               } else {
-                       return Status::newFatal( new RawMessage(
-                               $status->getWikiText( 'confirmemail_sendfailed' )
-                       ) );
-               }
-       }
-
-       /**
-        * Attempt to confirm the user's email address and show success or failure
-        * as needed; if successful, take the user to log in
-        *
-        * @param string $code Confirmation code
-        */
-       private function attemptConfirm( $code ) {
-               $user = User::newFromConfirmationCode( $code, User::READ_EXCLUSIVE );
-               if ( !is_object( $user ) ) {
-                       $this->getOutput()->addWikiMsg( 'confirmemail_invalid' );
-
-                       return;
-               }
-
-               // rate limit email confirmations
-               if ( $user->pingLimiter( 'confirmemail' ) ) {
-                       $this->getOutput()->addWikiMsg( 'actionthrottledtext' );
-
-                       return;
-               }
-
-               $user->confirmEmail();
-               $user->saveSettings();
-               $message = $this->getUser()->isLoggedIn() ? 'confirmemail_loggedin' : 'confirmemail_success';
-               $this->getOutput()->addWikiMsg( $message );
-
-               if ( !$this->getUser()->isLoggedIn() ) {
-                       $title = SpecialPage::getTitleFor( 'Userlogin' );
-                       $this->getOutput()->returnToMain( true, $title );
-               }
-       }
-}
index 4599b22..e8b85fa 100644 (file)
@@ -126,7 +126,10 @@ class SpecialContributions extends IncludableSpecialPage {
 
                // Allows reverts to have the bot flag in recent changes. It is just here to
                // be passed in the form at the top of the page
-               if ( $user->isAllowed( 'markbotedits' ) && $request->getBool( 'bot' ) ) {
+               if ( MediaWikiServices::getInstance()
+                                ->getPermissionManager()
+                                ->userHasRight( $user, 'markbotedits' ) && $request->getBool( 'bot' )
+               ) {
                        $this->opts['bot'] = '1';
                }
 
@@ -373,7 +376,9 @@ class SpecialContributions extends IncludableSpecialPage {
                        );
                }
 
-               if ( $sp->getUser()->isAllowed( 'block' ) ) { # Block / Change block / Unblock links
+               # Block / Change block / Unblock links
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( $permissionManager->userHasRight( $sp->getUser(), 'block' ) ) {
                        if ( $target->getBlock() && $target->getBlock()->getType() != DatabaseBlock::TYPE_AUTO ) {
                                $tools['block'] = $linkRenderer->makeKnownLink( # Change block link
                                        SpecialPage::getTitleFor( 'Block', $username ),
@@ -400,7 +405,7 @@ class SpecialContributions extends IncludableSpecialPage {
                );
 
                # Suppression log link (T61120)
-               if ( $sp->getUser()->isAllowed( 'suppressionlog' ) ) {
+               if ( $permissionManager->userHasRight( $sp->getUser(), 'suppressionlog' ) ) {
                        $tools['log-suppression'] = $linkRenderer->makeKnownLink(
                                SpecialPage::getTitleFor( 'Log', 'suppress' ),
                                $sp->msg( 'sp-contributions-suppresslog', $username )->text(),
@@ -412,7 +417,7 @@ class SpecialContributions extends IncludableSpecialPage {
                # Don't show some links for IP ranges
                if ( !$isRange ) {
                        # Uploads: hide if IPs cannot upload (T220674)
-                       if ( !$isIP || $target->isAllowed( 'upload' ) ) {
+                       if ( !$isIP || $permissionManager->userHasRight( $target, 'upload' ) ) {
                                $tools['uploads'] = $linkRenderer->makeKnownLink(
                                        SpecialPage::getTitleFor( 'Listfiles', $username ),
                                        $sp->msg( 'sp-contributions-uploads' )->text()
@@ -428,7 +433,7 @@ class SpecialContributions extends IncludableSpecialPage {
 
                        # Add link to deleted user contributions for priviledged users
                        # Todo: T183457
-                       if ( $sp->getUser()->isAllowed( 'deletedhistory' ) ) {
+                       if ( $permissionManager->userHasRight( $sp->getUser(), 'deletedhistory' ) ) {
                                $tools['deletedcontribs'] = $linkRenderer->makeKnownLink(
                                        SpecialPage::getTitleFor( 'DeletedContributions', $username ),
                                        $sp->msg( 'sp-contributions-deleted', $username )->text()
@@ -554,13 +559,9 @@ class SpecialContributions extends IncludableSpecialPage {
                        $filterSelection = Html::rawElement( 'div', [], '' );
                }
 
-               $labelUsername = Xml::radioLabel(
+               $labelUsername = Xml::label(
                        $this->msg( 'sp-contributions-username' )->text(),
-                       'contribs',
-                       'user',
-                       'user',
-                       true,
-                       [ 'class' => 'mw-input' ]
+                       'mw-target-user-or-ip'
                );
                $input = Html::input(
                        'target',
@@ -632,7 +633,10 @@ class SpecialContributions extends IncludableSpecialPage {
 
                $filters = [];
 
-               if ( $this->getUser()->isAllowed( 'deletedhistory' ) ) {
+               if ( MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'deletedhistory' )
+               ) {
                        $filters[] = Html::rawElement(
                                'span',
                                [ 'class' => 'mw-input-with-label' ],
index cc2fc80..637025c 100644 (file)
@@ -57,7 +57,9 @@ class SpecialCreateAccount extends LoginSignupSpecialPage {
        }
 
        public function userCanExecute( User $user ) {
-               return $user->isAllowed( 'createaccount' );
+               return MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $user, 'createaccount' );
        }
 
        public function checkPermissions() {
diff --git a/includes/specials/SpecialDeadendPages.php b/includes/specials/SpecialDeadendPages.php
new file mode 100644 (file)
index 0000000..9159442
--- /dev/null
@@ -0,0 +1,99 @@
+<?php
+/**
+ * Implements Special:Deadenpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * A special page that list pages that contain no link to other pages
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialDeadendPages extends PageQueryPage {
+
+       function __construct( $name = 'Deadendpages' ) {
+               parent::__construct( $name );
+       }
+
+       function getPageHeader() {
+               return $this->msg( 'deadendpagestext' )->parseAsBlock();
+       }
+
+       /**
+        * LEFT JOIN is expensive
+        *
+        * @return bool
+        */
+       function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       /**
+        * @return bool
+        */
+       function sortDescending() {
+               return false;
+       }
+
+       function getQueryInfo() {
+               return [
+                       'tables' => [ 'page', 'pagelinks' ],
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_title'
+                       ],
+                       'conds' => [
+                               'pl_from IS NULL',
+                               'page_namespace' => MediaWikiServices::getInstance()->getNamespaceInfo()->
+                                       getContentNamespaces(),
+                               'page_is_redirect' => 0
+                       ],
+                       'join_conds' => [
+                               'pagelinks' => [
+                                       'LEFT JOIN',
+                                       [ 'page_id=pl_from' ]
+                               ]
+                       ]
+               ];
+       }
+
+       function getOrderFields() {
+               // For some crazy reason ordering by a constant
+               // causes a filesort
+               if ( count( MediaWikiServices::getInstance()->getNamespaceInfo()->
+                       getContentNamespaces() ) > 1
+               ) {
+                       return [ 'page_namespace', 'page_title' ];
+               } else {
+                       return [ 'page_title' ];
+               }
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialDeadendpages.php b/includes/specials/SpecialDeadendpages.php
deleted file mode 100644 (file)
index 2a967c5..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-/**
- * Implements Special:Deadenpages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * A special page that list pages that contain no link to other pages
- *
- * @ingroup SpecialPage
- */
-class DeadendPagesPage extends PageQueryPage {
-
-       function __construct( $name = 'Deadendpages' ) {
-               parent::__construct( $name );
-       }
-
-       function getPageHeader() {
-               return $this->msg( 'deadendpagestext' )->parseAsBlock();
-       }
-
-       /**
-        * LEFT JOIN is expensive
-        *
-        * @return bool
-        */
-       function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       /**
-        * @return bool
-        */
-       function sortDescending() {
-               return false;
-       }
-
-       function getQueryInfo() {
-               return [
-                       'tables' => [ 'page', 'pagelinks' ],
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_title'
-                       ],
-                       'conds' => [
-                               'pl_from IS NULL',
-                               'page_namespace' => MediaWikiServices::getInstance()->getNamespaceInfo()->
-                                       getContentNamespaces(),
-                               'page_is_redirect' => 0
-                       ],
-                       'join_conds' => [
-                               'pagelinks' => [
-                                       'LEFT JOIN',
-                                       [ 'page_id=pl_from' ]
-                               ]
-                       ]
-               ];
-       }
-
-       function getOrderFields() {
-               // For some crazy reason ordering by a constant
-               // causes a filesort
-               if ( count( MediaWikiServices::getInstance()->getNamespaceInfo()->
-                       getContentNamespaces() ) > 1
-               ) {
-                       return [ 'page_namespace', 'page_title' ];
-               } else {
-                       return [ 'page_title' ];
-               }
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
index e9bf6a2..b2cd8c0 100644 (file)
@@ -28,7 +28,7 @@ use MediaWiki\MediaWikiServices;
  * Implements Special:DeletedContributions to display archived revisions
  * @ingroup SpecialPage
  */
-class DeletedContributionsPage extends SpecialPage {
+class SpecialDeletedContributions extends SpecialPage {
        /** @var FormOptions */
        protected $mOpts;
 
index fcf1bb2..540ac5a 100644 (file)
@@ -21,6 +21,7 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\Rdbms\IResultWrapper;
 use Wikimedia\Rdbms\IDatabase;
 
@@ -30,7 +31,7 @@ use Wikimedia\Rdbms\IDatabase;
  *
  * @ingroup SpecialPage
  */
-class DoubleRedirectsPage extends QueryPage {
+class SpecialDoubleRedirects extends QueryPage {
        function __construct( $name = 'DoubleRedirects' ) {
                parent::__construct( $name );
        }
@@ -155,7 +156,9 @@ class DoubleRedirectsPage extends QueryPage {
                // if the page is editable, add an edit link
                if (
                        // check user permissions
-                       $this->getUser()->isAllowed( 'edit' ) &&
+                       MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'edit' ) &&
                        // check, if the content model is editable through action=edit
                        ContentHandler::getForTitle( $titleA )->supportsDirectEditing()
                ) {
index 70a1bd4..48357aa 100644 (file)
@@ -19,6 +19,8 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\Permissions\PermissionManager;
+
 /**
  * Special page for adding and removing change tags to individual revisions.
  * A lot of this is copied out of SpecialRevisiondelete.
@@ -51,8 +53,18 @@ class SpecialEditTags extends UnlistedSpecialPage {
        /** @var string */
        private $reason;
 
-       public function __construct() {
+       /** @var PermissionManager */
+       private $permissionManager;
+
+       /**
+        * @inheritDoc
+        *
+        * @param PermissionManager $permissionManager
+        */
+       public function __construct( PermissionManager $permissionManager ) {
                parent::__construct( 'EditTags', 'changetags' );
+
+               $this->permissionManager = $permissionManager;
        }
 
        public function doesWrites() {
@@ -67,13 +79,6 @@ class SpecialEditTags extends UnlistedSpecialPage {
                $user = $this->getUser();
                $request = $this->getRequest();
 
-               // Check blocks
-               // @TODO Use PermissionManager::isBlockedFrom() instead.
-               $block = $user->getBlock();
-               if ( $block ) {
-                       throw new UserBlockedError( $block );
-               }
-
                $this->setHeaders();
                $this->outputHeader();
 
@@ -124,7 +129,7 @@ class SpecialEditTags extends UnlistedSpecialPage {
                        $this->ids
                );
 
-               $this->isAllowed = $user->isAllowed( 'changetags' );
+               $this->isAllowed = $this->permissionManager->userHasRight( $user, 'changetags' );
 
                $this->reason = $request->getVal( 'wpReason' );
                // We need a target page!
@@ -132,6 +137,12 @@ class SpecialEditTags extends UnlistedSpecialPage {
                        $output->addWikiMsg( 'undelete-header' );
                        return;
                }
+
+               // Check blocks
+               if ( $this->permissionManager->isBlockedFrom( $user, $this->targetObj ) ) {
+                       throw new UserBlockedError( $user->getBlock() );
+               }
+
                // Give a link to the logs/hist for this page
                $this->showConvenienceLinks();
 
index c54abad..7b9ee1a 100644 (file)
@@ -27,7 +27,7 @@
  *
  * @ingroup SpecialPage
  */
-class EmailInvalidation extends UnlistedSpecialPage {
+class SpecialEmailInvalidate extends UnlistedSpecialPage {
        public function __construct() {
                parent::__construct( 'Invalidateemail', 'editmyprivateinfo' );
        }
index b42cdea..c8b92bd 100644 (file)
@@ -253,7 +253,10 @@ class SpecialEmailUser extends UnlistedSpecialPage {
                        return 'mailnologin';
                }
 
-               if ( !$user->isAllowed( 'sendemail' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'sendemail' )
+               ) {
                        return 'badaccess';
                }
 
index ef1b3d8..72e881f 100644 (file)
@@ -273,7 +273,10 @@ class SpecialExpandTemplates extends SpecialPage {
                        // allowed and a valid edit token is not provided (T73111). However, MediaWiki
                        // does not currently provide logged-out users with CSRF protection; in that case,
                        // do not show the preview unless anonymous editing is allowed.
-                       if ( $user->isAnon() && !$user->isAllowed( 'edit' ) ) {
+                       if ( $user->isAnon() && !MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $user, 'edit' )
+                       ) {
                                $error = [ 'expand_templates_preview_fail_html_anon' ];
                        } elseif ( !$user->matchEditToken( $request->getVal( 'wpEditToken' ), '', $request ) ) {
                                $error = [ 'expand_templates_preview_fail_html' ];
@@ -282,7 +285,7 @@ class SpecialExpandTemplates extends SpecialPage {
                        }
 
                        if ( $error ) {
-                               $out->wrapWikiMsg( "<div class='previewnote'>\n$1\n</div>", $error );
+                               $out->wrapWikiMsg( "<div class='previewnote errorbox'>\n$1\n</div>", $error );
                                return;
                        }
                }
index 5a63581..e680d24 100644 (file)
@@ -327,7 +327,9 @@ class SpecialExport extends SpecialPage {
         * @return bool
         */
        private function userCanOverrideExportDepth() {
-               return $this->getUser()->isAllowed( 'override-export-depth' );
+               return MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $this->getUser(), 'override-export-depth' );
        }
 
        /**
diff --git a/includes/specials/SpecialFewestRevisions.php b/includes/specials/SpecialFewestRevisions.php
new file mode 100644 (file)
index 0000000..204d73a
--- /dev/null
@@ -0,0 +1,108 @@
+<?php
+/**
+ * Implements Special:Fewestrevisions
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Special page for listing the articles with the fewest revisions.
+ *
+ * @ingroup SpecialPage
+ * @author Martin Drashkov
+ */
+class SpecialFewestRevisions extends QueryPage {
+       function __construct( $name = 'Fewestrevisions' ) {
+               parent::__construct( $name );
+       }
+
+       public function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       public function getQueryInfo() {
+               return [
+                       'tables' => [ 'revision', 'page' ],
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'COUNT(*)',
+                       ],
+                       'conds' => [
+                               'page_namespace' => MediaWikiServices::getInstance()->getNamespaceInfo()->
+                                       getContentNamespaces(),
+                               'page_id = rev_page',
+                               'page_is_redirect = 0',
+                       ],
+                       'options' => [
+                               'GROUP BY' => [ 'page_namespace', 'page_title' ]
+                       ]
+               ];
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Database row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $nt = Title::makeTitleSafe( $result->namespace, $result->title );
+               if ( !$nt ) {
+                       return Html::element(
+                               'span',
+                               [ 'class' => 'mw-invalidtitle' ],
+                               Linker::getInvalidTitleDescription(
+                                       $this->getContext(),
+                                       $result->namespace,
+                                       $result->title
+                               )
+                       );
+               }
+               $linkRenderer = $this->getLinkRenderer();
+               $text = MediaWikiServices::getInstance()->getContentLanguage()->
+                       convert( htmlspecialchars( $nt->getPrefixedText() ) );
+               $plink = $linkRenderer->makeLink( $nt, new HtmlArmor( $text ) );
+
+               $nl = $this->msg( 'nrevisions' )->numParams( $result->value )->text();
+               $redirect = isset( $result->redirect ) && $result->redirect ?
+                       ' - ' . $this->msg( 'isredirect' )->escaped() : '';
+               $nlink = $linkRenderer->makeKnownLink(
+                       $nt,
+                       $nl,
+                       [],
+                       [ 'action' => 'history' ]
+               ) . $redirect;
+
+               return $this->getLanguage()->specialList( $plink, $nlink );
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialFewestrevisions.php b/includes/specials/SpecialFewestrevisions.php
deleted file mode 100644 (file)
index cf9da49..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-<?php
-/**
- * Implements Special:Fewestrevisions
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * Special page for listing the articles with the fewest revisions.
- *
- * @ingroup SpecialPage
- * @author Martin Drashkov
- */
-class FewestrevisionsPage extends QueryPage {
-       function __construct( $name = 'Fewestrevisions' ) {
-               parent::__construct( $name );
-       }
-
-       public function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       public function getQueryInfo() {
-               return [
-                       'tables' => [ 'revision', 'page' ],
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'COUNT(*)',
-                       ],
-                       'conds' => [
-                               'page_namespace' => MediaWikiServices::getInstance()->getNamespaceInfo()->
-                                       getContentNamespaces(),
-                               'page_id = rev_page',
-                               'page_is_redirect = 0',
-                       ],
-                       'options' => [
-                               'GROUP BY' => [ 'page_namespace', 'page_title' ]
-                       ]
-               ];
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Database row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $nt = Title::makeTitleSafe( $result->namespace, $result->title );
-               if ( !$nt ) {
-                       return Html::element(
-                               'span',
-                               [ 'class' => 'mw-invalidtitle' ],
-                               Linker::getInvalidTitleDescription(
-                                       $this->getContext(),
-                                       $result->namespace,
-                                       $result->title
-                               )
-                       );
-               }
-               $linkRenderer = $this->getLinkRenderer();
-               $text = MediaWikiServices::getInstance()->getContentLanguage()->
-                       convert( htmlspecialchars( $nt->getPrefixedText() ) );
-               $plink = $linkRenderer->makeLink( $nt, new HtmlArmor( $text ) );
-
-               $nl = $this->msg( 'nrevisions' )->numParams( $result->value )->text();
-               $redirect = isset( $result->redirect ) && $result->redirect ?
-                       ' - ' . $this->msg( 'isredirect' )->escaped() : '';
-               $nlink = $linkRenderer->makeKnownLink(
-                       $nt,
-                       $nl,
-                       [],
-                       [ 'action' => 'history' ]
-               ) . $redirect;
-
-               return $this->getLanguage()->specialList( $plink, $nlink );
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
index 5d8a415..f047e1f 100644 (file)
@@ -31,7 +31,7 @@ use MediaWiki\MediaWikiServices;
  *
  * @ingroup SpecialPage
  */
-class FileDuplicateSearchPage extends QueryPage {
+class SpecialFileDuplicateSearch extends QueryPage {
        protected $hash = '', $filename = '';
 
        /**
index f21c206..cfefa47 100644 (file)
@@ -135,18 +135,19 @@ class SpecialImport extends SpecialPage {
                }
 
                $user = $this->getUser();
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
                if ( !$user->matchEditToken( $request->getVal( 'editToken' ) ) ) {
                        $source = Status::newFatal( 'import-token-mismatch' );
                } elseif ( $this->sourceName === 'upload' ) {
                        $isUpload = true;
                        $this->usernamePrefix = $this->fullInterwikiPrefix = $request->getVal( 'usernamePrefix' );
-                       if ( $user->isAllowed( 'importupload' ) ) {
+                       if ( $permissionManager->userHasRight( $user, 'importupload' ) ) {
                                $source = ImportStreamSource::newFromUpload( "xmlimport" );
                        } else {
                                throw new PermissionsError( 'importupload' );
                        }
                } elseif ( $this->sourceName === 'interwiki' ) {
-                       if ( !$user->isAllowed( 'import' ) ) {
+                       if ( !$permissionManager->userHasRight( $user, 'import' ) ) {
                                throw new PermissionsError( 'import' );
                        }
                        $this->interwiki = $this->fullInterwikiPrefix = $request->getVal( 'interwiki' );
@@ -325,10 +326,11 @@ class SpecialImport extends SpecialPage {
        private function showForm() {
                $action = $this->getPageTitle()->getLocalURL( [ 'action' => 'submit' ] );
                $user = $this->getUser();
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
                $out = $this->getOutput();
                $this->addHelpLink( 'https://meta.wikimedia.org/wiki/Special:MyLanguage/Help:Import', true );
 
-               if ( $user->isAllowed( 'importupload' ) ) {
+               if ( $permissionManager->userHasRight( $user, 'importupload' ) ) {
                        $mappingSelection = $this->getMappingFormPart( 'upload' );
                        $out->addHTML(
                                Xml::fieldset( $this->msg( 'import-upload' )->text() ) .
@@ -401,7 +403,7 @@ class SpecialImport extends SpecialPage {
                        $out->addWikiMsg( 'importnosources' );
                }
 
-               if ( $user->isAllowed( 'import' ) && !empty( $this->importSources ) ) {
+               if ( $permissionManager->userHasRight( $user, 'import' ) && !empty( $this->importSources ) ) {
                        # Show input field for import depth only if $wgExportMaxLinkDepth > 0
                        $importDepth = '';
                        if ( $this->getConfig()->get( 'ExportMaxLinkDepth' ) > 0 ) {
index d08fe5c..60aedda 100644 (file)
@@ -29,9 +29,15 @@ use Wikimedia\Rdbms\IDatabase;
  * Special:LinkSearch to search the external-links table.
  * @ingroup SpecialPage
  */
-class LinkSearchPage extends QueryPage {
+class SpecialLinkSearch extends QueryPage {
        /** @var array|bool */
        private $mungedQuery = false;
+       /** @var string|null */
+       private $mQuery;
+       /** @var int|null */
+       private $mNs;
+       /** @var string|null */
+       private $mProt;
 
        function setParams( $params ) {
                $this->mQuery = $params['query'];
index c7430cc..d93c570 100644 (file)
@@ -32,7 +32,7 @@ use Wikimedia\Rdbms\IDatabase;
  *   a duplicate of the current version of some other file.
  * @ingroup SpecialPage
  */
-class ListDuplicatedFilesPage extends QueryPage {
+class SpecialListDuplicatedFiles extends QueryPage {
        function __construct( $name = 'ListDuplicatedFiles' ) {
                parent::__construct( $name );
        }
diff --git a/includes/specials/SpecialListRedirects.php b/includes/specials/SpecialListRedirects.php
new file mode 100644 (file)
index 0000000..e686273
--- /dev/null
@@ -0,0 +1,156 @@
+<?php
+/**
+ * Implements Special:Listredirects
+ *
+ * Copyright © 2006 Rob Church
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+use Wikimedia\Rdbms\IResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
+
+/**
+ * Special:Listredirects - Lists all the redirects on the wiki.
+ * @ingroup SpecialPage
+ */
+class SpecialListRedirects extends QueryPage {
+       function __construct( $name = 'Listredirects' ) {
+               parent::__construct( $name );
+       }
+
+       public function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       public function getQueryInfo() {
+               return [
+                       'tables' => [ 'p1' => 'page', 'redirect', 'p2' => 'page' ],
+                       'fields' => [ 'namespace' => 'p1.page_namespace',
+                               'title' => 'p1.page_title',
+                               'value' => 'p1.page_title',
+                               'rd_namespace',
+                               'rd_title',
+                               'rd_fragment',
+                               'rd_interwiki',
+                               'redirid' => 'p2.page_id' ],
+                       'conds' => [ 'p1.page_is_redirect' => 1 ],
+                       'join_conds' => [ 'redirect' => [
+                               'LEFT JOIN', 'rd_from=p1.page_id' ],
+                               'p2' => [ 'LEFT JOIN', [
+                                       'p2.page_namespace=rd_namespace',
+                                       'p2.page_title=rd_title' ] ] ]
+               ];
+       }
+
+       function getOrderFields() {
+               return [ 'p1.page_namespace', 'p1.page_title' ];
+       }
+
+       /**
+        * Cache page existence for performance
+        *
+        * @param IDatabase $db
+        * @param IResultWrapper $res
+        */
+       function preprocessResults( $db, $res ) {
+               if ( !$res->numRows() ) {
+                       return;
+               }
+
+               $batch = new LinkBatch;
+               foreach ( $res as $row ) {
+                       $batch->add( $row->namespace, $row->title );
+                       $redirTarget = $this->getRedirectTarget( $row );
+                       if ( $redirTarget ) {
+                               $batch->addObj( $redirTarget );
+                       }
+               }
+               $batch->execute();
+
+               // Back to start for display
+               $res->seek( 0 );
+       }
+
+       /**
+        * @param stdClass $row
+        * @return Title|null
+        */
+       protected function getRedirectTarget( $row ) {
+               if ( isset( $row->rd_title ) ) {
+                       return Title::makeTitle( $row->rd_namespace,
+                               $row->rd_title, $row->rd_fragment,
+                               $row->rd_interwiki
+                       );
+               } else {
+                       $title = Title::makeTitle( $row->namespace, $row->title );
+                       $article = WikiPage::factory( $title );
+
+                       return $article->getRedirectTarget();
+               }
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $linkRenderer = $this->getLinkRenderer();
+               # Make a link to the redirect itself
+               $rd_title = Title::makeTitle( $result->namespace, $result->title );
+               $rd_link = $linkRenderer->makeLink(
+                       $rd_title,
+                       null,
+                       [],
+                       [ 'redirect' => 'no' ]
+               );
+
+               # Find out where the redirect leads
+               $target = $this->getRedirectTarget( $result );
+               if ( $target ) {
+                       # Make a link to the destination page
+                       $lang = $this->getLanguage();
+                       $arr = $lang->getArrow() . $lang->getDirMark();
+                       $targetLink = $linkRenderer->makeLink( $target, $target->getFullText() );
+
+                       return "$rd_link $arr $targetLink";
+               } else {
+                       return "<del>$rd_link</del>";
+               }
+       }
+
+       public function execute( $par ) {
+               $this->addHelpLink( 'Help:Redirects' );
+               parent::execute( $par );
+       }
+
+       protected function getGroupName() {
+               return 'pages';
+       }
+}
diff --git a/includes/specials/SpecialListredirects.php b/includes/specials/SpecialListredirects.php
deleted file mode 100644 (file)
index 3284c57..0000000
+++ /dev/null
@@ -1,156 +0,0 @@
-<?php
-/**
- * Implements Special:Listredirects
- *
- * Copyright © 2006 Rob Church
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>
- */
-
-use Wikimedia\Rdbms\IResultWrapper;
-use Wikimedia\Rdbms\IDatabase;
-
-/**
- * Special:Listredirects - Lists all the redirects on the wiki.
- * @ingroup SpecialPage
- */
-class ListredirectsPage extends QueryPage {
-       function __construct( $name = 'Listredirects' ) {
-               parent::__construct( $name );
-       }
-
-       public function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       public function getQueryInfo() {
-               return [
-                       'tables' => [ 'p1' => 'page', 'redirect', 'p2' => 'page' ],
-                       'fields' => [ 'namespace' => 'p1.page_namespace',
-                               'title' => 'p1.page_title',
-                               'value' => 'p1.page_title',
-                               'rd_namespace',
-                               'rd_title',
-                               'rd_fragment',
-                               'rd_interwiki',
-                               'redirid' => 'p2.page_id' ],
-                       'conds' => [ 'p1.page_is_redirect' => 1 ],
-                       'join_conds' => [ 'redirect' => [
-                               'LEFT JOIN', 'rd_from=p1.page_id' ],
-                               'p2' => [ 'LEFT JOIN', [
-                                       'p2.page_namespace=rd_namespace',
-                                       'p2.page_title=rd_title' ] ] ]
-               ];
-       }
-
-       function getOrderFields() {
-               return [ 'p1.page_namespace', 'p1.page_title' ];
-       }
-
-       /**
-        * Cache page existence for performance
-        *
-        * @param IDatabase $db
-        * @param IResultWrapper $res
-        */
-       function preprocessResults( $db, $res ) {
-               if ( !$res->numRows() ) {
-                       return;
-               }
-
-               $batch = new LinkBatch;
-               foreach ( $res as $row ) {
-                       $batch->add( $row->namespace, $row->title );
-                       $redirTarget = $this->getRedirectTarget( $row );
-                       if ( $redirTarget ) {
-                               $batch->addObj( $redirTarget );
-                       }
-               }
-               $batch->execute();
-
-               // Back to start for display
-               $res->seek( 0 );
-       }
-
-       /**
-        * @param stdClass $row
-        * @return Title|null
-        */
-       protected function getRedirectTarget( $row ) {
-               if ( isset( $row->rd_title ) ) {
-                       return Title::makeTitle( $row->rd_namespace,
-                               $row->rd_title, $row->rd_fragment,
-                               $row->rd_interwiki
-                       );
-               } else {
-                       $title = Title::makeTitle( $row->namespace, $row->title );
-                       $article = WikiPage::factory( $title );
-
-                       return $article->getRedirectTarget();
-               }
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $linkRenderer = $this->getLinkRenderer();
-               # Make a link to the redirect itself
-               $rd_title = Title::makeTitle( $result->namespace, $result->title );
-               $rd_link = $linkRenderer->makeLink(
-                       $rd_title,
-                       null,
-                       [],
-                       [ 'redirect' => 'no' ]
-               );
-
-               # Find out where the redirect leads
-               $target = $this->getRedirectTarget( $result );
-               if ( $target ) {
-                       # Make a link to the destination page
-                       $lang = $this->getLanguage();
-                       $arr = $lang->getArrow() . $lang->getDirMark();
-                       $targetLink = $linkRenderer->makeLink( $target, $target->getFullText() );
-
-                       return "$rd_link $arr $targetLink";
-               } else {
-                       return "<del>$rd_link</del>";
-               }
-       }
-
-       public function execute( $par ) {
-               $this->addHelpLink( 'Help:Redirects' );
-               parent::execute( $par );
-       }
-
-       protected function getGroupName() {
-               return 'pages';
-       }
-}
index c6927c1..7c85814 100644 (file)
@@ -35,8 +35,6 @@ class SpecialLog extends SpecialPage {
        }
 
        public function execute( $par ) {
-               global $wgActorTableSchemaMigrationStage;
-
                $this->setHeaders();
                $this->outputHeader();
                $out = $this->getOutput();
@@ -96,7 +94,9 @@ class SpecialLog extends SpecialPage {
                if ( !LogPage::isLogType( $type ) ) {
                        $opts->setValue( 'type', '' );
                } elseif ( isset( $logRestrictions[$type] )
-                       && !$this->getUser()->isAllowed( $logRestrictions[$type] )
+                       && !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), $logRestrictions[$type] )
                ) {
                        throw new PermissionsError( $logRestrictions[$type] );
                }
@@ -107,13 +107,7 @@ class SpecialLog extends SpecialPage {
                        $offenderName = $opts->getValue( 'offender' );
                        $offender = empty( $offenderName ) ? null : User::newFromName( $offenderName, false );
                        if ( $offender ) {
-                               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                                       $qc = [ 'ls_field' => 'target_author_actor', 'ls_value' => $offender->getActorId() ];
-                               } elseif ( $offender->getId() > 0 ) {
-                                       $qc = [ 'ls_field' => 'target_author_id', 'ls_value' => $offender->getId() ];
-                               } else {
-                                       $qc = [ 'ls_field' => 'target_author_ip', 'ls_value' => $offender->getName() ];
-                               }
+                               $qc = [ 'ls_field' => 'target_author_actor', 'ls_value' => $offender->getActorId() ];
                        }
                } else {
                        // Allow extensions to add relations to their search types
diff --git a/includes/specials/SpecialLonelyPages.php b/includes/specials/SpecialLonelyPages.php
new file mode 100644 (file)
index 0000000..14f9435
--- /dev/null
@@ -0,0 +1,107 @@
+<?php
+/**
+ * Implements Special:Lonelypaages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * A special page looking for articles with no article linking to them,
+ * thus being lonely.
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialLonelyPages extends PageQueryPage {
+       function __construct( $name = 'Lonelypages' ) {
+               parent::__construct( $name );
+       }
+
+       function getPageHeader() {
+               return $this->msg( 'lonelypagestext' )->parseAsBlock();
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       function getQueryInfo() {
+               $tables = [ 'page', 'pagelinks', 'templatelinks' ];
+               $conds = [
+                       'pl_namespace IS NULL',
+                       'page_namespace' => MediaWikiServices::getInstance()->getNamespaceInfo()->
+                               getContentNamespaces(),
+                       'page_is_redirect' => 0,
+                       'tl_namespace IS NULL'
+               ];
+               $joinConds = [
+                       'pagelinks' => [
+                               'LEFT JOIN', [
+                                       'pl_namespace = page_namespace',
+                                       'pl_title = page_title'
+                               ]
+                       ],
+                       'templatelinks' => [
+                               'LEFT JOIN', [
+                                       'tl_namespace = page_namespace',
+                                       'tl_title = page_title'
+                               ]
+                       ]
+               ];
+
+               // Allow extensions to modify the query
+               Hooks::run( 'LonelyPagesQuery', [ &$tables, &$conds, &$joinConds ] );
+
+               return [
+                       'tables' => $tables,
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_title'
+                       ],
+                       'conds' => $conds,
+                       'join_conds' => $joinConds
+               ];
+       }
+
+       function getOrderFields() {
+               // For some crazy reason ordering by a constant
+               // causes a filesort in MySQL 5
+               if ( count( MediaWikiServices::getInstance()->getNamespaceInfo()->
+                       getContentNamespaces() ) > 1
+               ) {
+                       return [ 'page_namespace', 'page_title' ];
+               } else {
+                       return [ 'page_title' ];
+               }
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialLonelypages.php b/includes/specials/SpecialLonelypages.php
deleted file mode 100644 (file)
index ca3f4da..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-<?php
-/**
- * Implements Special:Lonelypaages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * A special page looking for articles with no article linking to them,
- * thus being lonely.
- *
- * @ingroup SpecialPage
- */
-class LonelyPagesPage extends PageQueryPage {
-       function __construct( $name = 'Lonelypages' ) {
-               parent::__construct( $name );
-       }
-
-       function getPageHeader() {
-               return $this->msg( 'lonelypagestext' )->parseAsBlock();
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       function getQueryInfo() {
-               $tables = [ 'page', 'pagelinks', 'templatelinks' ];
-               $conds = [
-                       'pl_namespace IS NULL',
-                       'page_namespace' => MediaWikiServices::getInstance()->getNamespaceInfo()->
-                               getContentNamespaces(),
-                       'page_is_redirect' => 0,
-                       'tl_namespace IS NULL'
-               ];
-               $joinConds = [
-                       'pagelinks' => [
-                               'LEFT JOIN', [
-                                       'pl_namespace = page_namespace',
-                                       'pl_title = page_title'
-                               ]
-                       ],
-                       'templatelinks' => [
-                               'LEFT JOIN', [
-                                       'tl_namespace = page_namespace',
-                                       'tl_title = page_title'
-                               ]
-                       ]
-               ];
-
-               // Allow extensions to modify the query
-               Hooks::run( 'LonelyPagesQuery', [ &$tables, &$conds, &$joinConds ] );
-
-               return [
-                       'tables' => $tables,
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_title'
-                       ],
-                       'conds' => $conds,
-                       'join_conds' => $joinConds
-               ];
-       }
-
-       function getOrderFields() {
-               // For some crazy reason ordering by a constant
-               // causes a filesort in MySQL 5
-               if ( count( MediaWikiServices::getInstance()->getNamespaceInfo()->
-                       getContentNamespaces() ) > 1
-               ) {
-                       return [ 'page_namespace', 'page_title' ];
-               } else {
-                       return [ 'page_title' ];
-               }
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
diff --git a/includes/specials/SpecialLongPages.php b/includes/specials/SpecialLongPages.php
new file mode 100644 (file)
index 0000000..5227d4e
--- /dev/null
@@ -0,0 +1,40 @@
+<?php
+/**
+ * Implements Special:Longpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialLongPages extends SpecialShortPages {
+       function __construct( $name = 'Longpages' ) {
+               parent::__construct( $name );
+       }
+
+       function sortDescending() {
+               return true;
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialLongpages.php b/includes/specials/SpecialLongpages.php
deleted file mode 100644 (file)
index d90d271..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-<?php
-/**
- * Implements Special:Longpages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-/**
- *
- * @ingroup SpecialPage
- */
-class LongPagesPage extends ShortPagesPage {
-       function __construct( $name = 'Longpages' ) {
-               parent::__construct( $name );
-       }
-
-       function sortDescending() {
-               return true;
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
diff --git a/includes/specials/SpecialMIMESearch.php b/includes/specials/SpecialMIMESearch.php
new file mode 100644 (file)
index 0000000..0784821
--- /dev/null
@@ -0,0 +1,244 @@
+<?php
+/**
+ * Implements Special:MIMESearch
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Searches the database for files of the requested MIME type, comparing this with the
+ * 'img_major_mime' and 'img_minor_mime' fields in the image table.
+ * @ingroup SpecialPage
+ */
+class SpecialMIMESearch extends QueryPage {
+       protected $major, $minor, $mime;
+
+       function __construct( $name = 'MIMEsearch' ) {
+               parent::__construct( $name );
+       }
+
+       public function isExpensive() {
+               return false;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       function isCacheable() {
+               return false;
+       }
+
+       function linkParameters() {
+               return [ 'mime' => "{$this->major}/{$this->minor}" ];
+       }
+
+       public function getQueryInfo() {
+               $minorType = [];
+               if ( $this->minor !== '*' ) {
+                       // Allow wildcard searching
+                       $minorType['img_minor_mime'] = $this->minor;
+               }
+               $imgQuery = LocalFile::getQueryInfo();
+               $qi = [
+                       'tables' => $imgQuery['tables'],
+                       'fields' => [
+                               'namespace' => NS_FILE,
+                               'title' => 'img_name',
+                               // Still have a value field just in case,
+                               // but it isn't actually used for sorting.
+                               'value' => 'img_name',
+                               'img_size',
+                               'img_width',
+                               'img_height',
+                               'img_user_text' => $imgQuery['fields']['img_user_text'],
+                               'img_timestamp'
+                       ],
+                       'conds' => [
+                               'img_major_mime' => $this->major,
+                               // This is in order to trigger using
+                               // the img_media_mime index in "range" mode.
+                               // @todo how is order defined? use MimeAnalyzer::getMediaTypes?
+                               'img_media_type' => [
+                                       MEDIATYPE_BITMAP,
+                                       MEDIATYPE_DRAWING,
+                                       MEDIATYPE_AUDIO,
+                                       MEDIATYPE_VIDEO,
+                                       MEDIATYPE_MULTIMEDIA,
+                                       MEDIATYPE_UNKNOWN,
+                                       MEDIATYPE_OFFICE,
+                                       MEDIATYPE_TEXT,
+                                       MEDIATYPE_EXECUTABLE,
+                                       MEDIATYPE_ARCHIVE,
+                                       MEDIATYPE_3D,
+                               ],
+                       ] + $minorType,
+                       'join_conds' => $imgQuery['joins'],
+               ];
+
+               return $qi;
+       }
+
+       /**
+        * The index is on (img_media_type, img_major_mime, img_minor_mime)
+        * which unfortunately doesn't have img_name at the end for sorting.
+        * So tell db to sort it however it wishes (Its not super important
+        * that this report gives results in a logical order). As an aditional
+        * note, mysql seems to by default order things by img_name ASC, which
+        * is what we ideally want, so everything works out fine anyhow.
+        * @return array
+        */
+       function getOrderFields() {
+               return [];
+       }
+
+       /**
+        * Generate and output the form
+        */
+       function getPageHeader() {
+               $formDescriptor = [
+                       'mime' => [
+                               'type' => 'combobox',
+                               'options' => $this->getSuggestionsForTypes(),
+                               'name' => 'mime',
+                               'label-message' => 'mimetype',
+                               'required' => true,
+                               'default' => $this->mime,
+                       ],
+               ];
+
+               HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
+                       ->setSubmitTextMsg( 'ilsubmit' )
+                       ->setAction( $this->getPageTitle()->getLocalURL() )
+                       ->setMethod( 'get' )
+                       ->prepareForm()
+                       ->displayForm( false );
+               return '';
+       }
+
+       protected function getSuggestionsForTypes() {
+               $dbr = wfGetDB( DB_REPLICA );
+               $lastMajor = null;
+               $suggestions = [];
+               $result = $dbr->select(
+                       [ 'image' ],
+                       // We ignore img_media_type, but using it in the query is needed for MySQL to choose a
+                       // sensible execution plan
+                       [ 'img_media_type', 'img_major_mime', 'img_minor_mime' ],
+                       [],
+                       __METHOD__,
+                       [ 'GROUP BY' => [ 'img_media_type', 'img_major_mime', 'img_minor_mime' ] ]
+               );
+               foreach ( $result as $row ) {
+                       $major = $row->img_major_mime;
+                       $minor = $row->img_minor_mime;
+                       $suggestions[ "$major/$minor" ] = "$major/$minor";
+                       if ( $lastMajor === $major ) {
+                               // If there are at least two with the same major mime type, also include the wildcard
+                               $suggestions[ "$major/*" ] = "$major/*";
+                       }
+                       $lastMajor = $major;
+               }
+               ksort( $suggestions );
+               return $suggestions;
+       }
+
+       public function execute( $par ) {
+               $this->addHelpLink( 'Help:Managing_files' );
+               $this->mime = $par ?: $this->getRequest()->getText( 'mime' );
+               $this->mime = trim( $this->mime );
+               list( $this->major, $this->minor ) = File::splitMime( $this->mime );
+
+               if ( $this->major == '' || $this->minor == '' || $this->minor == 'unknown' ||
+                       !self::isValidType( $this->major )
+               ) {
+                       $this->setHeaders();
+                       $this->outputHeader();
+                       $this->getPageHeader();
+                       return;
+               }
+
+               parent::execute( $par );
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $linkRenderer = $this->getLinkRenderer();
+               $nt = Title::makeTitle( $result->namespace, $result->title );
+               $text = MediaWikiServices::getInstance()->getContentLanguage()
+                       ->convert( htmlspecialchars( $nt->getText() ) );
+               $plink = $linkRenderer->makeLink(
+                       Title::newFromText( $nt->getPrefixedText() ),
+                       new HtmlArmor( $text )
+               );
+
+               $download = Linker::makeMediaLinkObj( $nt, $this->msg( 'download' )->escaped() );
+               $download = $this->msg( 'parentheses' )->rawParams( $download )->escaped();
+               $lang = $this->getLanguage();
+               $bytes = htmlspecialchars( $lang->formatSize( $result->img_size ) );
+               $dimensions = $this->msg( 'widthheight' )->numParams( $result->img_width,
+                       $result->img_height )->escaped();
+               $user = $linkRenderer->makeLink(
+                       Title::makeTitle( NS_USER, $result->img_user_text ),
+                       $result->img_user_text
+               );
+
+               $time = $lang->userTimeAndDate( $result->img_timestamp, $this->getUser() );
+               $time = htmlspecialchars( $time );
+
+               return "$download $plink . . $dimensions . . $bytes . . $user . . $time";
+       }
+
+       /**
+        * @param string $type
+        * @return bool
+        */
+       protected static function isValidType( $type ) {
+               // From maintenance/tables.sql => img_major_mime
+               $types = [
+                       'unknown',
+                       'application',
+                       'audio',
+                       'image',
+                       'text',
+                       'video',
+                       'message',
+                       'model',
+                       'multipart',
+                       'chemical'
+               ];
+
+               return in_array( $type, $types );
+       }
+
+       public function preprocessResults( $db, $res ) {
+               $this->executeLBFromResultWrapper( $res );
+       }
+
+       protected function getGroupName() {
+               return 'media';
+       }
+}
diff --git a/includes/specials/SpecialMIMEsearch.php b/includes/specials/SpecialMIMEsearch.php
deleted file mode 100644 (file)
index d6ace1d..0000000
+++ /dev/null
@@ -1,244 +0,0 @@
-<?php
-/**
- * Implements Special:MIMESearch
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * Searches the database for files of the requested MIME type, comparing this with the
- * 'img_major_mime' and 'img_minor_mime' fields in the image table.
- * @ingroup SpecialPage
- */
-class MIMEsearchPage extends QueryPage {
-       protected $major, $minor, $mime;
-
-       function __construct( $name = 'MIMEsearch' ) {
-               parent::__construct( $name );
-       }
-
-       public function isExpensive() {
-               return false;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       function isCacheable() {
-               return false;
-       }
-
-       function linkParameters() {
-               return [ 'mime' => "{$this->major}/{$this->minor}" ];
-       }
-
-       public function getQueryInfo() {
-               $minorType = [];
-               if ( $this->minor !== '*' ) {
-                       // Allow wildcard searching
-                       $minorType['img_minor_mime'] = $this->minor;
-               }
-               $imgQuery = LocalFile::getQueryInfo();
-               $qi = [
-                       'tables' => $imgQuery['tables'],
-                       'fields' => [
-                               'namespace' => NS_FILE,
-                               'title' => 'img_name',
-                               // Still have a value field just in case,
-                               // but it isn't actually used for sorting.
-                               'value' => 'img_name',
-                               'img_size',
-                               'img_width',
-                               'img_height',
-                               'img_user_text' => $imgQuery['fields']['img_user_text'],
-                               'img_timestamp'
-                       ],
-                       'conds' => [
-                               'img_major_mime' => $this->major,
-                               // This is in order to trigger using
-                               // the img_media_mime index in "range" mode.
-                               // @todo how is order defined? use MimeAnalyzer::getMediaTypes?
-                               'img_media_type' => [
-                                       MEDIATYPE_BITMAP,
-                                       MEDIATYPE_DRAWING,
-                                       MEDIATYPE_AUDIO,
-                                       MEDIATYPE_VIDEO,
-                                       MEDIATYPE_MULTIMEDIA,
-                                       MEDIATYPE_UNKNOWN,
-                                       MEDIATYPE_OFFICE,
-                                       MEDIATYPE_TEXT,
-                                       MEDIATYPE_EXECUTABLE,
-                                       MEDIATYPE_ARCHIVE,
-                                       MEDIATYPE_3D,
-                               ],
-                       ] + $minorType,
-                       'join_conds' => $imgQuery['joins'],
-               ];
-
-               return $qi;
-       }
-
-       /**
-        * The index is on (img_media_type, img_major_mime, img_minor_mime)
-        * which unfortunately doesn't have img_name at the end for sorting.
-        * So tell db to sort it however it wishes (Its not super important
-        * that this report gives results in a logical order). As an aditional
-        * note, mysql seems to by default order things by img_name ASC, which
-        * is what we ideally want, so everything works out fine anyhow.
-        * @return array
-        */
-       function getOrderFields() {
-               return [];
-       }
-
-       /**
-        * Generate and output the form
-        */
-       function getPageHeader() {
-               $formDescriptor = [
-                       'mime' => [
-                               'type' => 'combobox',
-                               'options' => $this->getSuggestionsForTypes(),
-                               'name' => 'mime',
-                               'label-message' => 'mimetype',
-                               'required' => true,
-                               'default' => $this->mime,
-                       ],
-               ];
-
-               HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() )
-                       ->setSubmitTextMsg( 'ilsubmit' )
-                       ->setAction( $this->getPageTitle()->getLocalURL() )
-                       ->setMethod( 'get' )
-                       ->prepareForm()
-                       ->displayForm( false );
-               return '';
-       }
-
-       protected function getSuggestionsForTypes() {
-               $dbr = wfGetDB( DB_REPLICA );
-               $lastMajor = null;
-               $suggestions = [];
-               $result = $dbr->select(
-                       [ 'image' ],
-                       // We ignore img_media_type, but using it in the query is needed for MySQL to choose a
-                       // sensible execution plan
-                       [ 'img_media_type', 'img_major_mime', 'img_minor_mime' ],
-                       [],
-                       __METHOD__,
-                       [ 'GROUP BY' => [ 'img_media_type', 'img_major_mime', 'img_minor_mime' ] ]
-               );
-               foreach ( $result as $row ) {
-                       $major = $row->img_major_mime;
-                       $minor = $row->img_minor_mime;
-                       $suggestions[ "$major/$minor" ] = "$major/$minor";
-                       if ( $lastMajor === $major ) {
-                               // If there are at least two with the same major mime type, also include the wildcard
-                               $suggestions[ "$major/*" ] = "$major/*";
-                       }
-                       $lastMajor = $major;
-               }
-               ksort( $suggestions );
-               return $suggestions;
-       }
-
-       public function execute( $par ) {
-               $this->addHelpLink( 'Help:Managing_files' );
-               $this->mime = $par ?: $this->getRequest()->getText( 'mime' );
-               $this->mime = trim( $this->mime );
-               list( $this->major, $this->minor ) = File::splitMime( $this->mime );
-
-               if ( $this->major == '' || $this->minor == '' || $this->minor == 'unknown' ||
-                       !self::isValidType( $this->major )
-               ) {
-                       $this->setHeaders();
-                       $this->outputHeader();
-                       $this->getPageHeader();
-                       return;
-               }
-
-               parent::execute( $par );
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $linkRenderer = $this->getLinkRenderer();
-               $nt = Title::makeTitle( $result->namespace, $result->title );
-               $text = MediaWikiServices::getInstance()->getContentLanguage()
-                       ->convert( htmlspecialchars( $nt->getText() ) );
-               $plink = $linkRenderer->makeLink(
-                       Title::newFromText( $nt->getPrefixedText() ),
-                       new HtmlArmor( $text )
-               );
-
-               $download = Linker::makeMediaLinkObj( $nt, $this->msg( 'download' )->escaped() );
-               $download = $this->msg( 'parentheses' )->rawParams( $download )->escaped();
-               $lang = $this->getLanguage();
-               $bytes = htmlspecialchars( $lang->formatSize( $result->img_size ) );
-               $dimensions = $this->msg( 'widthheight' )->numParams( $result->img_width,
-                       $result->img_height )->escaped();
-               $user = $linkRenderer->makeLink(
-                       Title::makeTitle( NS_USER, $result->img_user_text ),
-                       $result->img_user_text
-               );
-
-               $time = $lang->userTimeAndDate( $result->img_timestamp, $this->getUser() );
-               $time = htmlspecialchars( $time );
-
-               return "$download $plink . . $dimensions . . $bytes . . $user . . $time";
-       }
-
-       /**
-        * @param string $type
-        * @return bool
-        */
-       protected static function isValidType( $type ) {
-               // From maintenance/tables.sql => img_major_mime
-               $types = [
-                       'unknown',
-                       'application',
-                       'audio',
-                       'image',
-                       'text',
-                       'video',
-                       'message',
-                       'model',
-                       'multipart',
-                       'chemical'
-               ];
-
-               return in_array( $type, $types );
-       }
-
-       public function preprocessResults( $db, $res ) {
-               $this->executeLBFromResultWrapper( $res );
-       }
-
-       protected function getGroupName() {
-               return 'media';
-       }
-}
index 45bd524..333d9b3 100644 (file)
@@ -28,7 +28,7 @@ use Wikimedia\Rdbms\IDatabase;
 /**
  * @ingroup SpecialPage
  */
-class MediaStatisticsPage extends QueryPage {
+class SpecialMediaStatistics extends QueryPage {
        protected $totalCount = 0, $totalBytes = 0;
 
        /**
diff --git a/includes/specials/SpecialMostCategories.php b/includes/specials/SpecialMostCategories.php
new file mode 100644 (file)
index 0000000..682a23a
--- /dev/null
@@ -0,0 +1,114 @@
+<?php
+/**
+ * Implements Special:Mostcategories
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ */
+
+use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
+
+/**
+ * A special page that list pages that have highest category count
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialMostCategories extends QueryPage {
+       function __construct( $name = 'Mostcategories' ) {
+               parent::__construct( $name );
+       }
+
+       public function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       public function getQueryInfo() {
+               return [
+                       'tables' => [ 'categorylinks', 'page' ],
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'COUNT(*)'
+                       ],
+                       'conds' => [ 'page_namespace' =>
+                               MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces() ],
+                       'options' => [
+                               'HAVING' => 'COUNT(*) > 1',
+                               'GROUP BY' => [ 'page_namespace', 'page_title' ]
+                       ],
+                       'join_conds' => [
+                               'page' => [
+                                       'LEFT JOIN',
+                                       'page_id = cl_from'
+                               ]
+                       ]
+               ];
+       }
+
+       /**
+        * @param IDatabase $db
+        * @param IResultWrapper $res
+        */
+       function preprocessResults( $db, $res ) {
+               $this->executeLBFromResultWrapper( $res );
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $title = Title::makeTitleSafe( $result->namespace, $result->title );
+               if ( !$title ) {
+                       return Html::element(
+                               'span',
+                               [ 'class' => 'mw-invalidtitle' ],
+                               Linker::getInvalidTitleDescription(
+                                       $this->getContext(),
+                                       $result->namespace,
+                                       $result->title
+                               )
+                       );
+               }
+
+               $linkRenderer = $this->getLinkRenderer();
+               if ( $this->isCached() ) {
+                       $link = $linkRenderer->makeLink( $title );
+               } else {
+                       $link = $linkRenderer->makeKnownLink( $title );
+               }
+
+               $count = $this->msg( 'ncategories' )->numParams( $result->value )->escaped();
+
+               return $this->getLanguage()->specialList( $link, $count );
+       }
+
+       protected function getGroupName() {
+               return 'highuse';
+       }
+}
diff --git a/includes/specials/SpecialMostInterwikis.php b/includes/specials/SpecialMostInterwikis.php
new file mode 100644 (file)
index 0000000..52777b0
--- /dev/null
@@ -0,0 +1,117 @@
+<?php
+/**
+ * Implements Special:Mostinterwikis
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
+
+/**
+ * A special page that listed pages that have highest interwiki count
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialMostInterwikis extends QueryPage {
+       function __construct( $name = 'Mostinterwikis' ) {
+               parent::__construct( $name );
+       }
+
+       public function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       public function getQueryInfo() {
+               return [
+                       'tables' => [
+                               'langlinks',
+                               'page'
+                       ], 'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'COUNT(*)'
+                       ], 'conds' => [
+                               'page_namespace' =>
+                                       MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces()
+                       ], 'options' => [
+                               'HAVING' => 'COUNT(*) > 1',
+                               'GROUP BY' => [
+                                       'page_namespace',
+                                       'page_title'
+                               ]
+                       ], 'join_conds' => [
+                               'page' => [
+                                       'LEFT JOIN',
+                                       'page_id = ll_from'
+                               ]
+                       ]
+               ];
+       }
+
+       /**
+        * Pre-fill the link cache
+        *
+        * @param IDatabase $db
+        * @param IResultWrapper $res
+        */
+       function preprocessResults( $db, $res ) {
+               $this->executeLBFromResultWrapper( $res );
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $title = Title::makeTitleSafe( $result->namespace, $result->title );
+               if ( !$title ) {
+                       return Html::element(
+                               'span',
+                               [ 'class' => 'mw-invalidtitle' ],
+                               Linker::getInvalidTitleDescription(
+                                       $this->getContext(),
+                                       $result->namespace,
+                                       $result->title
+                               )
+                       );
+               }
+
+               $linkRenderer = $this->getLinkRenderer();
+               if ( $this->isCached() ) {
+                       $link = $linkRenderer->makeLink( $title );
+               } else {
+                       $link = $linkRenderer->makeKnownLink( $title );
+               }
+
+               $count = $this->msg( 'ninterwikis' )->numParams( $result->value )->escaped();
+
+               return $this->getLanguage()->specialList( $link, $count );
+       }
+
+       protected function getGroupName() {
+               return 'highuse';
+       }
+}
diff --git a/includes/specials/SpecialMostLinked.php b/includes/specials/SpecialMostLinked.php
new file mode 100644 (file)
index 0000000..c0f1a2a
--- /dev/null
@@ -0,0 +1,135 @@
+<?php
+/**
+ * Implements Special:Mostlinked
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason, 2006 Rob Church
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+use Wikimedia\Rdbms\IResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
+
+/**
+ * A special page to show pages ordered by the number of pages linking to them.
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialMostLinked extends QueryPage {
+       function __construct( $name = 'Mostlinked' ) {
+               parent::__construct( $name );
+       }
+
+       public function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       public function getQueryInfo() {
+               return [
+                       'tables' => [ 'pagelinks', 'page' ],
+                       'fields' => [
+                               'namespace' => 'pl_namespace',
+                               'title' => 'pl_title',
+                               'value' => 'COUNT(*)',
+                               'page_namespace'
+                       ],
+                       'options' => [
+                               'HAVING' => 'COUNT(*) > 1',
+                               'GROUP BY' => [
+                                       'pl_namespace', 'pl_title',
+                                       'page_namespace'
+                               ]
+                       ],
+                       'join_conds' => [
+                               'page' => [
+                                       'LEFT JOIN',
+                                       [
+                                               'page_namespace = pl_namespace',
+                                               'page_title = pl_title'
+                                       ]
+                               ]
+                       ]
+               ];
+       }
+
+       /**
+        * Pre-fill the link cache
+        *
+        * @param IDatabase $db
+        * @param IResultWrapper $res
+        */
+       function preprocessResults( $db, $res ) {
+               $this->executeLBFromResultWrapper( $res );
+       }
+
+       /**
+        * Make a link to "what links here" for the specified title
+        *
+        * @param Title $title Title being queried
+        * @param string $caption Text to display on the link
+        * @return string
+        */
+       function makeWlhLink( $title, $caption ) {
+               $wlh = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedDBkey() );
+
+               $linkRenderer = $this->getLinkRenderer();
+               return $linkRenderer->makeKnownLink( $wlh, $caption );
+       }
+
+       /**
+        * Make links to the page corresponding to the item,
+        * and the "what links here" page for it
+        *
+        * @param Skin $skin Skin to be used
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $title = Title::makeTitleSafe( $result->namespace, $result->title );
+               if ( !$title ) {
+                       return Html::element(
+                               'span',
+                               [ 'class' => 'mw-invalidtitle' ],
+                               Linker::getInvalidTitleDescription(
+                                       $this->getContext(),
+                                       $result->namespace,
+                                       $result->title )
+                       );
+               }
+
+               $linkRenderer = $this->getLinkRenderer();
+               $link = $linkRenderer->makeLink( $title );
+               $wlh = $this->makeWlhLink(
+                       $title,
+                       $this->msg( 'nlinks' )->numParams( $result->value )->text()
+               );
+
+               return $this->getLanguage()->specialList( $link, $wlh );
+       }
+
+       protected function getGroupName() {
+               return 'highuse';
+       }
+}
diff --git a/includes/specials/SpecialMostLinkedCategories.php b/includes/specials/SpecialMostLinkedCategories.php
new file mode 100644 (file)
index 0000000..32157fa
--- /dev/null
@@ -0,0 +1,98 @@
+<?php
+/**
+ * Implements Special:Mostlinkedcategories
+ *
+ * Copyright © 2005, Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ */
+
+use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
+
+/**
+ * A querypage to show categories ordered in descending order by the pages in them
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialMostLinkedCategories extends QueryPage {
+       function __construct( $name = 'Mostlinkedcategories' ) {
+               parent::__construct( $name );
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       public function getQueryInfo() {
+               return [
+                       'tables' => [ 'category' ],
+                       'fields' => [ 'title' => 'cat_title',
+                               'namespace' => NS_CATEGORY,
+                               'value' => 'cat_pages' ],
+                       'conds' => [ 'cat_pages > 0' ],
+               ];
+       }
+
+       function sortDescending() {
+               return true;
+       }
+
+       /**
+        * Fetch user page links and cache their existence
+        *
+        * @param IDatabase $db
+        * @param IResultWrapper $res
+        */
+       function preprocessResults( $db, $res ) {
+               $this->executeLBFromResultWrapper( $res );
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $nt = Title::makeTitleSafe( NS_CATEGORY, $result->title );
+               if ( !$nt ) {
+                       return Html::element(
+                               'span',
+                               [ 'class' => 'mw-invalidtitle' ],
+                               Linker::getInvalidTitleDescription(
+                                       $this->getContext(),
+                                       NS_CATEGORY,
+                                       $result->title )
+                       );
+               }
+
+               $text = MediaWikiServices::getInstance()->getContentLanguage()
+                       ->convert( htmlspecialchars( $nt->getText() ) );
+               $plink = $this->getLinkRenderer()->makeLink( $nt, new HtmlArmor( $text ) );
+               $nlinks = $this->msg( 'nmembers' )->numParams( $result->value )->escaped();
+
+               return $this->getLanguage()->specialList( $plink, $nlinks );
+       }
+
+       protected function getGroupName() {
+               return 'highuse';
+       }
+}
diff --git a/includes/specials/SpecialMostLinkedTemplates.php b/includes/specials/SpecialMostLinkedTemplates.php
new file mode 100644 (file)
index 0000000..f7122c2
--- /dev/null
@@ -0,0 +1,132 @@
+<?php
+/**
+ * Implements Special:Mostlinkedtemplates
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+use Wikimedia\Rdbms\IResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
+
+/**
+ * Special page lists templates with a large number of
+ * transclusion links, i.e. "most used" templates
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialMostLinkedTemplates extends QueryPage {
+       function __construct( $name = 'Mostlinkedtemplates' ) {
+               parent::__construct( $name );
+       }
+
+       /**
+        * Is this report expensive, i.e should it be cached?
+        *
+        * @return bool
+        */
+       public function isExpensive() {
+               return true;
+       }
+
+       /**
+        * Is there a feed available?
+        *
+        * @return bool
+        */
+       public function isSyndicated() {
+               return false;
+       }
+
+       /**
+        * Sort the results in descending order?
+        *
+        * @return bool
+        */
+       public function sortDescending() {
+               return true;
+       }
+
+       public function getQueryInfo() {
+               return [
+                       'tables' => [ 'templatelinks' ],
+                       'fields' => [
+                               'namespace' => 'tl_namespace',
+                               'title' => 'tl_title',
+                               'value' => 'COUNT(*)'
+                       ],
+                       'options' => [ 'GROUP BY' => [ 'tl_namespace', 'tl_title' ] ]
+               ];
+       }
+
+       /**
+        * Pre-cache page existence to speed up link generation
+        *
+        * @param IDatabase $db
+        * @param IResultWrapper $res
+        */
+       public function preprocessResults( $db, $res ) {
+               $this->executeLBFromResultWrapper( $res );
+       }
+
+       /**
+        * Format a result row
+        *
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       public function formatResult( $skin, $result ) {
+               $title = Title::makeTitleSafe( $result->namespace, $result->title );
+               if ( !$title ) {
+                       return Html::element(
+                               'span',
+                               [ 'class' => 'mw-invalidtitle' ],
+                               Linker::getInvalidTitleDescription(
+                                       $this->getContext(),
+                                       $result->namespace,
+                                       $result->title
+                               )
+                       );
+               }
+
+               return $this->getLanguage()->specialList(
+                       $this->getLinkRenderer()->makeLink( $title ),
+                       $this->makeWlhLink( $title, $result )
+               );
+       }
+
+       /**
+        * Make a "what links here" link for a given title
+        *
+        * @param Title $title Title to make the link for
+        * @param object $result Result row
+        * @return string
+        */
+       private function makeWlhLink( $title, $result ) {
+               $wlh = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedText() );
+               $label = $this->msg( 'ntransclusions' )->numParams( $result->value )->text();
+
+               return $this->getLinkRenderer()->makeLink( $wlh, $label );
+       }
+
+       protected function getGroupName() {
+               return 'highuse';
+       }
+}
diff --git a/includes/specials/SpecialMostRevisions.php b/includes/specials/SpecialMostRevisions.php
new file mode 100644 (file)
index 0000000..60e0fe7
--- /dev/null
@@ -0,0 +1,39 @@
+<?php
+/**
+ * Implements Special:Mostrevisions
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ */
+
+class SpecialMostRevisions extends SpecialFewestRevisions {
+       function __construct( $name = 'Mostrevisions' ) {
+               parent::__construct( $name );
+       }
+
+       function sortDescending() {
+               return true;
+       }
+
+       protected function getGroupName() {
+               return 'highuse';
+       }
+}
diff --git a/includes/specials/SpecialMostcategories.php b/includes/specials/SpecialMostcategories.php
deleted file mode 100644 (file)
index 0dd9437..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-<?php
-/**
- * Implements Special:Mostcategories
- *
- * Copyright © 2005 Ævar Arnfjörð Bjarmason
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- */
-
-use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\IResultWrapper;
-use Wikimedia\Rdbms\IDatabase;
-
-/**
- * A special page that list pages that have highest category count
- *
- * @ingroup SpecialPage
- */
-class MostcategoriesPage extends QueryPage {
-       function __construct( $name = 'Mostcategories' ) {
-               parent::__construct( $name );
-       }
-
-       public function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       public function getQueryInfo() {
-               return [
-                       'tables' => [ 'categorylinks', 'page' ],
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'COUNT(*)'
-                       ],
-                       'conds' => [ 'page_namespace' =>
-                               MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces() ],
-                       'options' => [
-                               'HAVING' => 'COUNT(*) > 1',
-                               'GROUP BY' => [ 'page_namespace', 'page_title' ]
-                       ],
-                       'join_conds' => [
-                               'page' => [
-                                       'LEFT JOIN',
-                                       'page_id = cl_from'
-                               ]
-                       ]
-               ];
-       }
-
-       /**
-        * @param IDatabase $db
-        * @param IResultWrapper $res
-        */
-       function preprocessResults( $db, $res ) {
-               $this->executeLBFromResultWrapper( $res );
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $title = Title::makeTitleSafe( $result->namespace, $result->title );
-               if ( !$title ) {
-                       return Html::element(
-                               'span',
-                               [ 'class' => 'mw-invalidtitle' ],
-                               Linker::getInvalidTitleDescription(
-                                       $this->getContext(),
-                                       $result->namespace,
-                                       $result->title
-                               )
-                       );
-               }
-
-               $linkRenderer = $this->getLinkRenderer();
-               if ( $this->isCached() ) {
-                       $link = $linkRenderer->makeLink( $title );
-               } else {
-                       $link = $linkRenderer->makeKnownLink( $title );
-               }
-
-               $count = $this->msg( 'ncategories' )->numParams( $result->value )->escaped();
-
-               return $this->getLanguage()->specialList( $link, $count );
-       }
-
-       protected function getGroupName() {
-               return 'highuse';
-       }
-}
diff --git a/includes/specials/SpecialMostinterwikis.php b/includes/specials/SpecialMostinterwikis.php
deleted file mode 100644 (file)
index 0fcf842..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-<?php
-/**
- * Implements Special:Mostinterwikis
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\IResultWrapper;
-use Wikimedia\Rdbms\IDatabase;
-
-/**
- * A special page that listed pages that have highest interwiki count
- *
- * @ingroup SpecialPage
- */
-class MostinterwikisPage extends QueryPage {
-       function __construct( $name = 'Mostinterwikis' ) {
-               parent::__construct( $name );
-       }
-
-       public function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       public function getQueryInfo() {
-               return [
-                       'tables' => [
-                               'langlinks',
-                               'page'
-                       ], 'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'COUNT(*)'
-                       ], 'conds' => [
-                               'page_namespace' =>
-                                       MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces()
-                       ], 'options' => [
-                               'HAVING' => 'COUNT(*) > 1',
-                               'GROUP BY' => [
-                                       'page_namespace',
-                                       'page_title'
-                               ]
-                       ], 'join_conds' => [
-                               'page' => [
-                                       'LEFT JOIN',
-                                       'page_id = ll_from'
-                               ]
-                       ]
-               ];
-       }
-
-       /**
-        * Pre-fill the link cache
-        *
-        * @param IDatabase $db
-        * @param IResultWrapper $res
-        */
-       function preprocessResults( $db, $res ) {
-               $this->executeLBFromResultWrapper( $res );
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $title = Title::makeTitleSafe( $result->namespace, $result->title );
-               if ( !$title ) {
-                       return Html::element(
-                               'span',
-                               [ 'class' => 'mw-invalidtitle' ],
-                               Linker::getInvalidTitleDescription(
-                                       $this->getContext(),
-                                       $result->namespace,
-                                       $result->title
-                               )
-                       );
-               }
-
-               $linkRenderer = $this->getLinkRenderer();
-               if ( $this->isCached() ) {
-                       $link = $linkRenderer->makeLink( $title );
-               } else {
-                       $link = $linkRenderer->makeKnownLink( $title );
-               }
-
-               $count = $this->msg( 'ninterwikis' )->numParams( $result->value )->escaped();
-
-               return $this->getLanguage()->specialList( $link, $count );
-       }
-
-       protected function getGroupName() {
-               return 'highuse';
-       }
-}
diff --git a/includes/specials/SpecialMostlinked.php b/includes/specials/SpecialMostlinked.php
deleted file mode 100644 (file)
index c4553a4..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-<?php
-/**
- * Implements Special:Mostlinked
- *
- * Copyright © 2005 Ævar Arnfjörð Bjarmason, 2006 Rob Church
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * @author Rob Church <robchur@gmail.com>
- */
-
-use Wikimedia\Rdbms\IResultWrapper;
-use Wikimedia\Rdbms\IDatabase;
-
-/**
- * A special page to show pages ordered by the number of pages linking to them.
- *
- * @ingroup SpecialPage
- */
-class MostlinkedPage extends QueryPage {
-       function __construct( $name = 'Mostlinked' ) {
-               parent::__construct( $name );
-       }
-
-       public function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       public function getQueryInfo() {
-               return [
-                       'tables' => [ 'pagelinks', 'page' ],
-                       'fields' => [
-                               'namespace' => 'pl_namespace',
-                               'title' => 'pl_title',
-                               'value' => 'COUNT(*)',
-                               'page_namespace'
-                       ],
-                       'options' => [
-                               'HAVING' => 'COUNT(*) > 1',
-                               'GROUP BY' => [
-                                       'pl_namespace', 'pl_title',
-                                       'page_namespace'
-                               ]
-                       ],
-                       'join_conds' => [
-                               'page' => [
-                                       'LEFT JOIN',
-                                       [
-                                               'page_namespace = pl_namespace',
-                                               'page_title = pl_title'
-                                       ]
-                               ]
-                       ]
-               ];
-       }
-
-       /**
-        * Pre-fill the link cache
-        *
-        * @param IDatabase $db
-        * @param IResultWrapper $res
-        */
-       function preprocessResults( $db, $res ) {
-               $this->executeLBFromResultWrapper( $res );
-       }
-
-       /**
-        * Make a link to "what links here" for the specified title
-        *
-        * @param Title $title Title being queried
-        * @param string $caption Text to display on the link
-        * @return string
-        */
-       function makeWlhLink( $title, $caption ) {
-               $wlh = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedDBkey() );
-
-               $linkRenderer = $this->getLinkRenderer();
-               return $linkRenderer->makeKnownLink( $wlh, $caption );
-       }
-
-       /**
-        * Make links to the page corresponding to the item,
-        * and the "what links here" page for it
-        *
-        * @param Skin $skin Skin to be used
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $title = Title::makeTitleSafe( $result->namespace, $result->title );
-               if ( !$title ) {
-                       return Html::element(
-                               'span',
-                               [ 'class' => 'mw-invalidtitle' ],
-                               Linker::getInvalidTitleDescription(
-                                       $this->getContext(),
-                                       $result->namespace,
-                                       $result->title )
-                       );
-               }
-
-               $linkRenderer = $this->getLinkRenderer();
-               $link = $linkRenderer->makeLink( $title );
-               $wlh = $this->makeWlhLink(
-                       $title,
-                       $this->msg( 'nlinks' )->numParams( $result->value )->text()
-               );
-
-               return $this->getLanguage()->specialList( $link, $wlh );
-       }
-
-       protected function getGroupName() {
-               return 'highuse';
-       }
-}
diff --git a/includes/specials/SpecialMostlinkedcategories.php b/includes/specials/SpecialMostlinkedcategories.php
deleted file mode 100644 (file)
index 56a701a..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-<?php
-/**
- * Implements Special:Mostlinkedcategories
- *
- * Copyright © 2005, Ævar Arnfjörð Bjarmason
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- */
-
-use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\IResultWrapper;
-use Wikimedia\Rdbms\IDatabase;
-
-/**
- * A querypage to show categories ordered in descending order by the pages in them
- *
- * @ingroup SpecialPage
- */
-class MostlinkedCategoriesPage extends QueryPage {
-       function __construct( $name = 'Mostlinkedcategories' ) {
-               parent::__construct( $name );
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       public function getQueryInfo() {
-               return [
-                       'tables' => [ 'category' ],
-                       'fields' => [ 'title' => 'cat_title',
-                               'namespace' => NS_CATEGORY,
-                               'value' => 'cat_pages' ],
-                       'conds' => [ 'cat_pages > 0' ],
-               ];
-       }
-
-       function sortDescending() {
-               return true;
-       }
-
-       /**
-        * Fetch user page links and cache their existence
-        *
-        * @param IDatabase $db
-        * @param IResultWrapper $res
-        */
-       function preprocessResults( $db, $res ) {
-               $this->executeLBFromResultWrapper( $res );
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $nt = Title::makeTitleSafe( NS_CATEGORY, $result->title );
-               if ( !$nt ) {
-                       return Html::element(
-                               'span',
-                               [ 'class' => 'mw-invalidtitle' ],
-                               Linker::getInvalidTitleDescription(
-                                       $this->getContext(),
-                                       NS_CATEGORY,
-                                       $result->title )
-                       );
-               }
-
-               $text = MediaWikiServices::getInstance()->getContentLanguage()
-                       ->convert( htmlspecialchars( $nt->getText() ) );
-               $plink = $this->getLinkRenderer()->makeLink( $nt, new HtmlArmor( $text ) );
-               $nlinks = $this->msg( 'nmembers' )->numParams( $result->value )->escaped();
-
-               return $this->getLanguage()->specialList( $plink, $nlinks );
-       }
-
-       protected function getGroupName() {
-               return 'highuse';
-       }
-}
diff --git a/includes/specials/SpecialMostlinkedtemplates.php b/includes/specials/SpecialMostlinkedtemplates.php
deleted file mode 100644 (file)
index 4544468..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-<?php
-/**
- * Implements Special:Mostlinkedtemplates
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>
- */
-
-use Wikimedia\Rdbms\IResultWrapper;
-use Wikimedia\Rdbms\IDatabase;
-
-/**
- * Special page lists templates with a large number of
- * transclusion links, i.e. "most used" templates
- *
- * @ingroup SpecialPage
- */
-class MostlinkedTemplatesPage extends QueryPage {
-       function __construct( $name = 'Mostlinkedtemplates' ) {
-               parent::__construct( $name );
-       }
-
-       /**
-        * Is this report expensive, i.e should it be cached?
-        *
-        * @return bool
-        */
-       public function isExpensive() {
-               return true;
-       }
-
-       /**
-        * Is there a feed available?
-        *
-        * @return bool
-        */
-       public function isSyndicated() {
-               return false;
-       }
-
-       /**
-        * Sort the results in descending order?
-        *
-        * @return bool
-        */
-       public function sortDescending() {
-               return true;
-       }
-
-       public function getQueryInfo() {
-               return [
-                       'tables' => [ 'templatelinks' ],
-                       'fields' => [
-                               'namespace' => 'tl_namespace',
-                               'title' => 'tl_title',
-                               'value' => 'COUNT(*)'
-                       ],
-                       'options' => [ 'GROUP BY' => [ 'tl_namespace', 'tl_title' ] ]
-               ];
-       }
-
-       /**
-        * Pre-cache page existence to speed up link generation
-        *
-        * @param IDatabase $db
-        * @param IResultWrapper $res
-        */
-       public function preprocessResults( $db, $res ) {
-               $this->executeLBFromResultWrapper( $res );
-       }
-
-       /**
-        * Format a result row
-        *
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       public function formatResult( $skin, $result ) {
-               $title = Title::makeTitleSafe( $result->namespace, $result->title );
-               if ( !$title ) {
-                       return Html::element(
-                               'span',
-                               [ 'class' => 'mw-invalidtitle' ],
-                               Linker::getInvalidTitleDescription(
-                                       $this->getContext(),
-                                       $result->namespace,
-                                       $result->title
-                               )
-                       );
-               }
-
-               return $this->getLanguage()->specialList(
-                       $this->getLinkRenderer()->makeLink( $title ),
-                       $this->makeWlhLink( $title, $result )
-               );
-       }
-
-       /**
-        * Make a "what links here" link for a given title
-        *
-        * @param Title $title Title to make the link for
-        * @param object $result Result row
-        * @return string
-        */
-       private function makeWlhLink( $title, $result ) {
-               $wlh = SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedText() );
-               $label = $this->msg( 'ntransclusions' )->numParams( $result->value )->text();
-
-               return $this->getLinkRenderer()->makeLink( $wlh, $label );
-       }
-
-       protected function getGroupName() {
-               return 'highuse';
-       }
-}
diff --git a/includes/specials/SpecialMostrevisions.php b/includes/specials/SpecialMostrevisions.php
deleted file mode 100644 (file)
index 0471caf..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-<?php
-/**
- * Implements Special:Mostrevisions
- *
- * Copyright © 2005 Ævar Arnfjörð Bjarmason
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- */
-
-class MostrevisionsPage extends FewestrevisionsPage {
-       function __construct( $name = 'Mostrevisions' ) {
-               parent::__construct( $name );
-       }
-
-       function sortDescending() {
-               return true;
-       }
-
-       protected function getGroupName() {
-               return 'highuse';
-       }
-}
index 6da362d..0767faf 100644 (file)
@@ -209,7 +209,9 @@ class MovePageForm extends UnlistedSpecialPage {
                }
 
                if ( count( $err ) == 1 && isset( $err[0][0] ) && $err[0][0] == 'file-exists-sharedrepo'
-                       && $user->isAllowed( 'reupload-shared' )
+                       && MediaWikiServices::getInstance()
+                                ->getPermissionManager()
+                                ->userHasRight( $user, 'reupload-shared' )
                ) {
                        $out->wrapWikiMsg(
                                "<div class='warningbox'>\n$1\n</div>\n",
@@ -374,7 +376,10 @@ class MovePageForm extends UnlistedSpecialPage {
                        );
                }
 
-               if ( $user->isAllowed( 'suppressredirect' ) ) {
+               if ( MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'suppressredirect' )
+               ) {
                        if ( $handlerSupportsRedirects ) {
                                $isChecked = $this->leaveRedirect;
                                $isDisabled = false;
@@ -520,6 +525,7 @@ class MovePageForm extends UnlistedSpecialPage {
 
        function doSubmit() {
                $user = $this->getUser();
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
 
                if ( $user->pingLimiter( 'move' ) ) {
                        throw new ThrottledError;
@@ -540,7 +546,7 @@ class MovePageForm extends UnlistedSpecialPage {
                # Show a warning if the target file exists on a shared repo
                $repoGroup = $services->getRepoGroup();
                if ( $nt->getNamespace() == NS_FILE
-                       && !( $this->moveOverShared && $user->isAllowed( 'reupload-shared' ) )
+                       && !( $this->moveOverShared && $permissionManager->userHasRight( $user, 'reupload-shared' ) )
                        && !$repoGroup->getLocalRepo()->findFile( $nt )
                        && $repoGroup->findFile( $nt )
                ) {
@@ -551,7 +557,7 @@ class MovePageForm extends UnlistedSpecialPage {
 
                # Delete to make way if requested
                if ( $this->deleteAndMove ) {
-                       $permErrors = $nt->getUserPermissionsErrors( 'delete', $user );
+                       $permErrors = $permissionManager->getPermissionErrors( 'delete', $user, $nt );
                        if ( count( $permErrors ) ) {
                                # Only show the first error
                                $this->showForm( $permErrors, true );
@@ -592,7 +598,7 @@ class MovePageForm extends UnlistedSpecialPage {
 
                if ( !$handler->supportsRedirects() ) {
                        $createRedirect = false;
-               } elseif ( $user->isAllowed( 'suppressredirect' ) ) {
+               } elseif ( $permissionManager->userHasRight( $user, 'suppressredirect' ) ) {
                        $createRedirect = $this->leaveRedirect;
                } else {
                        $createRedirect = true;
@@ -607,7 +613,6 @@ class MovePageForm extends UnlistedSpecialPage {
                        $this->moveTalk = false;
                }
                if ( $this->moveSubpages ) {
-                       $permissionManager = $services->getPermissionManager();
                        $this->moveSubpages = $permissionManager->userCan( 'move-subpages', $user, $ot );
                }
 
diff --git a/includes/specials/SpecialNewFiles.php b/includes/specials/SpecialNewFiles.php
new file mode 100644 (file)
index 0000000..29e7789
--- /dev/null
@@ -0,0 +1,226 @@
+<?php
+/**
+ * Implements Special:Newimages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+
+class SpecialNewFiles extends IncludableSpecialPage {
+       /** @var FormOptions */
+       protected $opts;
+
+       /** @var string[] */
+       protected $mediaTypes;
+
+       public function __construct() {
+               parent::__construct( 'Newimages' );
+       }
+
+       public function execute( $par ) {
+               $context = new DerivativeContext( $this->getContext() );
+
+               $this->setHeaders();
+               $this->outputHeader();
+               $mimeAnalyzer = MediaWiki\MediaWikiServices::getInstance()->getMimeAnalyzer();
+               $this->mediaTypes = $mimeAnalyzer->getMediaTypes();
+
+               $out = $this->getOutput();
+               $this->addHelpLink( 'Help:New images' );
+
+               $opts = new FormOptions();
+
+               $opts->add( 'like', '' );
+               $opts->add( 'user', '' );
+               $opts->add( 'showbots', false );
+               $opts->add( 'hidepatrolled', false );
+               $opts->add( 'mediatype', $this->mediaTypes );
+               $opts->add( 'limit', 50 );
+               $opts->add( 'offset', '' );
+               $opts->add( 'start', '' );
+               $opts->add( 'end', '' );
+
+               $opts->fetchValuesFromRequest( $this->getRequest() );
+
+               if ( $par !== null ) {
+                       $opts->setValue( is_numeric( $par ) ? 'limit' : 'like', $par );
+               }
+
+               // If start date comes after end date chronologically, swap them.
+               // They are swapped in the interface by JS.
+               $start = $opts->getValue( 'start' );
+               $end = $opts->getValue( 'end' );
+               if ( $start !== '' && $end !== '' && $start > $end ) {
+                       $temp = $end;
+                       $end = $start;
+                       $start = $temp;
+
+                       $opts->setValue( 'start', $start, true );
+                       $opts->setValue( 'end', $end, true );
+
+                       // also swap values in request object, which is used by HTMLForm
+                       // to pre-populate the fields with the previous input
+                       $request = $context->getRequest();
+                       $context->setRequest( new DerivativeRequest(
+                               $request,
+                               [ 'start' => $start, 'end' => $end ] + $request->getValues(),
+                               $request->wasPosted()
+                       ) );
+               }
+
+               // if all media types have been selected, wipe out the array to prevent
+               // the pointless IN(...) query condition (which would have no effect
+               // because every possible type has been selected)
+               $missingMediaTypes = array_diff( $this->mediaTypes, $opts->getValue( 'mediatype' ) );
+               if ( empty( $missingMediaTypes ) ) {
+                       $opts->setValue( 'mediatype', [] );
+               }
+
+               $opts->validateIntBounds( 'limit', 0, 500 );
+
+               $this->opts = $opts;
+
+               if ( !$this->including() ) {
+                       $this->setTopText();
+                       $this->buildForm( $context );
+               }
+
+               $pager = new NewFilesPager( $context, $opts, $this->getLinkRenderer() );
+
+               $out->addHTML( $pager->getBody() );
+               if ( !$this->including() ) {
+                       $out->addHTML( $pager->getNavigationBar() );
+               }
+       }
+
+       protected function buildForm( IContextSource $context ) {
+               $mediaTypesText = array_map( function ( $type ) {
+                       // mediastatistics-header-unknown, mediastatistics-header-bitmap,
+                       // mediastatistics-header-drawing, mediastatistics-header-audio,
+                       // mediastatistics-header-video, mediastatistics-header-multimedia,
+                       // mediastatistics-header-office, mediastatistics-header-text,
+                       // mediastatistics-header-executable, mediastatistics-header-archive,
+                       // mediastatistics-header-3d,
+                       return $this->msg( 'mediastatistics-header-' . strtolower( $type ) )->text();
+               }, $this->mediaTypes );
+               $mediaTypesOptions = array_combine( $mediaTypesText, $this->mediaTypes );
+               ksort( $mediaTypesOptions );
+
+               $formDescriptor = [
+                       'like' => [
+                               'type' => 'text',
+                               'label-message' => 'newimages-label',
+                               'name' => 'like',
+                       ],
+
+                       'user' => [
+                               'class' => 'HTMLUserTextField',
+                               'label-message' => 'newimages-user',
+                               'name' => 'user',
+                       ],
+
+                       'showbots' => [
+                               'type' => 'check',
+                               'label-message' => 'newimages-showbots',
+                               'name' => 'showbots',
+                       ],
+
+                       'hidepatrolled' => [
+                               'type' => 'check',
+                               'label-message' => 'newimages-hidepatrolled',
+                               'name' => 'hidepatrolled',
+                       ],
+
+                       'mediatype' => [
+                               'type' => 'multiselect',
+                               'flatlist' => true,
+                               'name' => 'mediatype',
+                               'label-message' => 'newimages-mediatype',
+                               'options' => $mediaTypesOptions,
+                               'default' => $this->mediaTypes,
+                       ],
+
+                       'limit' => [
+                               'type' => 'hidden',
+                               'default' => $this->opts->getValue( 'limit' ),
+                               'name' => 'limit',
+                       ],
+
+                       'offset' => [
+                               'type' => 'hidden',
+                               'default' => $this->opts->getValue( 'offset' ),
+                               'name' => 'offset',
+                       ],
+
+                       'start' => [
+                               'type' => 'date',
+                               'label-message' => 'date-range-from',
+                               'name' => 'start',
+                       ],
+
+                       'end' => [
+                               'type' => 'date',
+                               'label-message' => 'date-range-to',
+                               'name' => 'end',
+                       ],
+               ];
+
+               if ( $this->getConfig()->get( 'MiserMode' ) ) {
+                       unset( $formDescriptor['like'] );
+               }
+
+               if ( !$this->getUser()->useFilePatrol() ) {
+                       unset( $formDescriptor['hidepatrolled'] );
+               }
+
+               HTMLForm::factory( 'ooui', $formDescriptor, $context )
+                       // For the 'multiselect' field values to be preserved on submit
+                       ->setFormIdentifier( 'specialnewimages' )
+                       ->setWrapperLegendMsg( 'newimages-legend' )
+                       ->setSubmitTextMsg( 'ilsubmit' )
+                       ->setMethod( 'get' )
+                       ->prepareForm()
+                       ->displayForm( false );
+       }
+
+       protected function getGroupName() {
+               return 'changes';
+       }
+
+       /**
+        * Send the text to be displayed above the options
+        */
+       function setTopText() {
+               $message = $this->msg( 'newimagestext' )->inContentLanguage();
+               if ( !$message->isDisabled() ) {
+                       $contLang = MediaWikiServices::getInstance()->getContentLanguage();
+                       $this->getOutput()->addWikiTextAsContent(
+                               Html::rawElement( 'div',
+                                       [
+
+                                               'lang' => $contLang->getHtmlCode(),
+                                               'dir' => $contLang->getDir()
+                                       ],
+                                       "\n" . $message->plain() . "\n"
+                               )
+                       );
+               }
+       }
+}
diff --git a/includes/specials/SpecialNewimages.php b/includes/specials/SpecialNewimages.php
deleted file mode 100644 (file)
index 29e7789..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-<?php
-/**
- * Implements Special:Newimages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-use MediaWiki\MediaWikiServices;
-
-class SpecialNewFiles extends IncludableSpecialPage {
-       /** @var FormOptions */
-       protected $opts;
-
-       /** @var string[] */
-       protected $mediaTypes;
-
-       public function __construct() {
-               parent::__construct( 'Newimages' );
-       }
-
-       public function execute( $par ) {
-               $context = new DerivativeContext( $this->getContext() );
-
-               $this->setHeaders();
-               $this->outputHeader();
-               $mimeAnalyzer = MediaWiki\MediaWikiServices::getInstance()->getMimeAnalyzer();
-               $this->mediaTypes = $mimeAnalyzer->getMediaTypes();
-
-               $out = $this->getOutput();
-               $this->addHelpLink( 'Help:New images' );
-
-               $opts = new FormOptions();
-
-               $opts->add( 'like', '' );
-               $opts->add( 'user', '' );
-               $opts->add( 'showbots', false );
-               $opts->add( 'hidepatrolled', false );
-               $opts->add( 'mediatype', $this->mediaTypes );
-               $opts->add( 'limit', 50 );
-               $opts->add( 'offset', '' );
-               $opts->add( 'start', '' );
-               $opts->add( 'end', '' );
-
-               $opts->fetchValuesFromRequest( $this->getRequest() );
-
-               if ( $par !== null ) {
-                       $opts->setValue( is_numeric( $par ) ? 'limit' : 'like', $par );
-               }
-
-               // If start date comes after end date chronologically, swap them.
-               // They are swapped in the interface by JS.
-               $start = $opts->getValue( 'start' );
-               $end = $opts->getValue( 'end' );
-               if ( $start !== '' && $end !== '' && $start > $end ) {
-                       $temp = $end;
-                       $end = $start;
-                       $start = $temp;
-
-                       $opts->setValue( 'start', $start, true );
-                       $opts->setValue( 'end', $end, true );
-
-                       // also swap values in request object, which is used by HTMLForm
-                       // to pre-populate the fields with the previous input
-                       $request = $context->getRequest();
-                       $context->setRequest( new DerivativeRequest(
-                               $request,
-                               [ 'start' => $start, 'end' => $end ] + $request->getValues(),
-                               $request->wasPosted()
-                       ) );
-               }
-
-               // if all media types have been selected, wipe out the array to prevent
-               // the pointless IN(...) query condition (which would have no effect
-               // because every possible type has been selected)
-               $missingMediaTypes = array_diff( $this->mediaTypes, $opts->getValue( 'mediatype' ) );
-               if ( empty( $missingMediaTypes ) ) {
-                       $opts->setValue( 'mediatype', [] );
-               }
-
-               $opts->validateIntBounds( 'limit', 0, 500 );
-
-               $this->opts = $opts;
-
-               if ( !$this->including() ) {
-                       $this->setTopText();
-                       $this->buildForm( $context );
-               }
-
-               $pager = new NewFilesPager( $context, $opts, $this->getLinkRenderer() );
-
-               $out->addHTML( $pager->getBody() );
-               if ( !$this->including() ) {
-                       $out->addHTML( $pager->getNavigationBar() );
-               }
-       }
-
-       protected function buildForm( IContextSource $context ) {
-               $mediaTypesText = array_map( function ( $type ) {
-                       // mediastatistics-header-unknown, mediastatistics-header-bitmap,
-                       // mediastatistics-header-drawing, mediastatistics-header-audio,
-                       // mediastatistics-header-video, mediastatistics-header-multimedia,
-                       // mediastatistics-header-office, mediastatistics-header-text,
-                       // mediastatistics-header-executable, mediastatistics-header-archive,
-                       // mediastatistics-header-3d,
-                       return $this->msg( 'mediastatistics-header-' . strtolower( $type ) )->text();
-               }, $this->mediaTypes );
-               $mediaTypesOptions = array_combine( $mediaTypesText, $this->mediaTypes );
-               ksort( $mediaTypesOptions );
-
-               $formDescriptor = [
-                       'like' => [
-                               'type' => 'text',
-                               'label-message' => 'newimages-label',
-                               'name' => 'like',
-                       ],
-
-                       'user' => [
-                               'class' => 'HTMLUserTextField',
-                               'label-message' => 'newimages-user',
-                               'name' => 'user',
-                       ],
-
-                       'showbots' => [
-                               'type' => 'check',
-                               'label-message' => 'newimages-showbots',
-                               'name' => 'showbots',
-                       ],
-
-                       'hidepatrolled' => [
-                               'type' => 'check',
-                               'label-message' => 'newimages-hidepatrolled',
-                               'name' => 'hidepatrolled',
-                       ],
-
-                       'mediatype' => [
-                               'type' => 'multiselect',
-                               'flatlist' => true,
-                               'name' => 'mediatype',
-                               'label-message' => 'newimages-mediatype',
-                               'options' => $mediaTypesOptions,
-                               'default' => $this->mediaTypes,
-                       ],
-
-                       'limit' => [
-                               'type' => 'hidden',
-                               'default' => $this->opts->getValue( 'limit' ),
-                               'name' => 'limit',
-                       ],
-
-                       'offset' => [
-                               'type' => 'hidden',
-                               'default' => $this->opts->getValue( 'offset' ),
-                               'name' => 'offset',
-                       ],
-
-                       'start' => [
-                               'type' => 'date',
-                               'label-message' => 'date-range-from',
-                               'name' => 'start',
-                       ],
-
-                       'end' => [
-                               'type' => 'date',
-                               'label-message' => 'date-range-to',
-                               'name' => 'end',
-                       ],
-               ];
-
-               if ( $this->getConfig()->get( 'MiserMode' ) ) {
-                       unset( $formDescriptor['like'] );
-               }
-
-               if ( !$this->getUser()->useFilePatrol() ) {
-                       unset( $formDescriptor['hidepatrolled'] );
-               }
-
-               HTMLForm::factory( 'ooui', $formDescriptor, $context )
-                       // For the 'multiselect' field values to be preserved on submit
-                       ->setFormIdentifier( 'specialnewimages' )
-                       ->setWrapperLegendMsg( 'newimages-legend' )
-                       ->setSubmitTextMsg( 'ilsubmit' )
-                       ->setMethod( 'get' )
-                       ->prepareForm()
-                       ->displayForm( false );
-       }
-
-       protected function getGroupName() {
-               return 'changes';
-       }
-
-       /**
-        * Send the text to be displayed above the options
-        */
-       function setTopText() {
-               $message = $this->msg( 'newimagestext' )->inContentLanguage();
-               if ( !$message->isDisabled() ) {
-                       $contLang = MediaWikiServices::getInstance()->getContentLanguage();
-                       $this->getOutput()->addWikiTextAsContent(
-                               Html::rawElement( 'div',
-                                       [
-
-                                               'lang' => $contLang->getHtmlCode(),
-                                               'dir' => $contLang->getDir()
-                                       ],
-                                       "\n" . $message->plain() . "\n"
-                               )
-                       );
-               }
-       }
-}
index 978efa7..df8bce1 100644 (file)
@@ -25,7 +25,6 @@
  * The web server should generally be configured to make this accessible via a canonical URL/URI,
  * such as <http://my.domain.org/data/main/Foo>.
  *
- * @class
  * @ingroup SpecialPage
  */
 class SpecialPageData extends SpecialPage {
index 3c009c3..527b910 100644 (file)
@@ -39,6 +39,11 @@ class SpecialPagesWithProp extends QueryPage {
         */
        private $existingPropNames = null;
 
+       /**
+        * @var string|null
+        */
+       private $ns;
+
        /**
         * @var bool
         */
@@ -78,6 +83,13 @@ class SpecialPagesWithProp extends QueryPage {
                                'label-message' => 'pageswithprop-prop',
                                'required' => true,
                        ],
+                       'namespace' => [
+                               'type' => 'namespaceselect',
+                               'name' => 'namespace',
+                               'label-message' => 'namespace',
+                               'all' => null,
+                               'default' => null,
+                       ],
                        'reverse' => [
                                'type' => 'check',
                                'name' => 'reverse',
@@ -108,6 +120,7 @@ class SpecialPagesWithProp extends QueryPage {
 
        public function onSubmit( $data, $form ) {
                $this->propName = $data['propname'];
+               $this->ns = $data['namespace'];
                parent::execute( $data['propname'] );
        }
 
@@ -134,7 +147,7 @@ class SpecialPagesWithProp extends QueryPage {
        }
 
        public function getQueryInfo() {
-               return [
+               $query = [
                        'tables' => [ 'page_props', 'page' ],
                        'fields' => [
                                'page_id' => 'pp_page',
@@ -153,6 +166,12 @@ class SpecialPagesWithProp extends QueryPage {
                        ],
                        'options' => []
                ];
+
+               if ( $this->ns && isset( $this->ns ) ) {
+                       $query['conds']['page_namespace'] = $this->ns;
+               }
+
+               return $query;
        }
 
        function getOrderFields() {
index 3524d79..2ef96ad 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 use MediaWiki\Auth\AuthManager;
+use MediaWiki\MediaWikiServices;
 
 /**
  * Special page for requesting a password reset email.
@@ -52,7 +53,11 @@ class SpecialPasswordReset extends FormSpecialPage {
 
        private function getPasswordReset() {
                if ( $this->passwordReset === null ) {
-                       $this->passwordReset = new PasswordReset( $this->getConfig(), AuthManager::singleton() );
+                       $this->passwordReset = new PasswordReset(
+                               $this->getConfig(),
+                               AuthManager::singleton(),
+                               MediaWikiServices::getInstance()->getPermissionManager()
+                       );
                }
                return $this->passwordReset;
        }
index 0bc9147..d541ead 100644 (file)
@@ -115,7 +115,10 @@ class SpecialPreferences extends SpecialPage {
        }
 
        protected function showResetForm() {
-               if ( !$this->getUser()->isAllowed( 'editmyoptions' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'editmyoptions' )
+               ) {
                        throw new PermissionsError( 'editmyoptions' );
                }
 
@@ -134,7 +137,10 @@ class SpecialPreferences extends SpecialPage {
        }
 
        public function submitReset( $formData ) {
-               if ( !$this->getUser()->isAllowed( 'editmyoptions' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'editmyoptions' )
+               ) {
                        throw new PermissionsError( 'editmyoptions' );
                }
 
index 0bfe185..4683fe6 100644 (file)
@@ -185,7 +185,9 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                if (
                        !$this->including() &&
                        $this->getUser()->isLoggedIn() &&
-                       $this->getUser()->isAllowed( 'viewmywatchlist' )
+                       MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'viewmywatchlist' )
                ) {
                        $this->registerFiltersFromDefinitions( [ $this->watchlistFilterGroupDefinition ] );
                        $watchlistGroup = $this->getFilterGroup( 'watchlist' );
@@ -279,7 +281,10 @@ class SpecialRecentChanges extends ChangesListSpecialPage {
                $join_conds = array_merge( $join_conds, $rcQuery['joins'] );
 
                // JOIN on watchlist for users
-               if ( $user->isLoggedIn() && $user->isAllowed( 'viewmywatchlist' ) ) {
+               if ( $user->isLoggedIn() && MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'viewmywatchlist' )
+               ) {
                        $tables[] = 'watchlist';
                        $fields[] = 'wl_user';
                        $fields[] = 'wl_notificationtimestamp';
index 26f3665..0921ada 100644 (file)
@@ -21,6 +21,8 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This is to display changes made to all articles linked in an article.
  *
@@ -91,7 +93,10 @@ class SpecialRecentChangesLinked extends SpecialRecentChanges {
 
                // left join with watchlist table to highlight watched rows
                $uid = $this->getUser()->getId();
-               if ( $uid && $this->getUser()->isAllowed( 'viewmywatchlist' ) ) {
+               if ( $uid && MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'viewmywatchlist' )
+               ) {
                        $tables[] = 'watchlist';
                        $select[] = 'wl_user';
                        $join_conds['watchlist'] = [ 'LEFT JOIN', [
index 50867dd..82d8b73 100644 (file)
@@ -90,7 +90,9 @@ class SpecialRedirect extends FormSpecialPage {
                }
                $userpage = Title::makeTitle( NS_USER, $username );
 
-               return Status::newGood( $userpage->getFullURL( '', false, PROTO_CURRENT ) );
+               return Status::newGood( [
+                       $userpage->getFullURL( '', false, PROTO_CURRENT ), 302
+               ] );
        }
 
        /**
index 7444225..698e590 100644 (file)
@@ -21,7 +21,9 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\MediaWikiServices;
 use MediaWiki\Storage\RevisionRecord;
+use MediaWiki\Permissions\PermissionManager;
 
 /**
  * Special page allowing users with the appropriate permissions to view
@@ -66,6 +68,9 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
        /** @var string */
        private $otherReason;
 
+       /** @var PermissionManager */
+       private $permissionManager;
+
        /**
         * UI labels for each type.
         */
@@ -107,8 +112,15 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                ],
        ];
 
-       public function __construct() {
+       /**
+        * @inheritDoc
+        *
+        * @param PermissionManager $permissionManager
+        */
+       public function __construct( PermissionManager $permissionManager ) {
                parent::__construct( 'Revisiondelete', 'deleterevision' );
+
+               $this->permissionManager = $permissionManager;
        }
 
        public function doesWrites() {
@@ -124,13 +136,6 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                $output = $this->getOutput();
                $user = $this->getUser();
 
-               // Check blocks
-               // @TODO Use PermissionManager::isBlockedFrom() instead.
-               $block = $user->getBlock();
-               if ( $block ) {
-                       throw new UserBlockedError( $block );
-               }
-
                $this->setHeaders();
                $this->outputHeader();
                $request = $this->getRequest();
@@ -180,12 +185,19 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        return;
                }
 
+               // Check blocks
+               if ( $this->permissionManager->isBlockedFrom( $user, $this->targetObj ) ) {
+                       throw new UserBlockedError( $user->getBlock() );
+               }
+
                $this->typeLabels = self::$UILabels[$this->typeName];
                $list = $this->getList();
                $list->reset();
-               $this->mIsAllowed = $user->isAllowed( RevisionDeleter::getRestriction( $this->typeName ) );
-               $canViewSuppressedOnly = $this->getUser()->isAllowed( 'viewsuppressed' ) &&
-                       !$this->getUser()->isAllowed( 'suppressrevision' );
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               $this->mIsAllowed = $permissionManager->userHasRight( $user,
+                       RevisionDeleter::getRestriction( $this->typeName ) );
+               $canViewSuppressedOnly = $permissionManager->userHasRight( $user, 'viewsuppressed' ) &&
+                       !$permissionManager->userHasRight( $user, 'suppressrevision' );
                $pageIsSuppressed = $list->areAnySuppressed();
                $this->mIsAllowed = $this->mIsAllowed && !( $canViewSuppressedOnly && $pageIsSuppressed );
 
@@ -202,7 +214,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        [ 'revdelete-hide-comment', 'wpHideComment', RevisionRecord::DELETED_COMMENT ],
                        [ 'revdelete-hide-user', 'wpHideUser', RevisionRecord::DELETED_USER ]
                ];
-               if ( $user->isAllowed( 'suppressrevision' ) ) {
+               if ( $permissionManager->userHasRight( $user, 'suppressrevision' ) ) {
                        $this->checks[] = [ 'revdelete-hide-restricted',
                                'wpHideRestricted', RevisionRecord::DELETED_RESTRICTED ];
                }
@@ -214,7 +226,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        $this->showForm();
                }
 
-               if ( $user->isAllowed( 'deletedhistory' ) ) {
+               if ( $permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
                        $qc = $this->getLogQueryCond();
                        # Show relevant lines from the deletion log
                        $deleteLogPage = new LogPage( 'delete' );
@@ -228,7 +240,7 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        );
                }
                # Show relevant lines from the suppression log
-               if ( $user->isAllowed( 'suppressionlog' ) ) {
+               if ( $permissionManager->userHasRight( $user, 'suppressionlog' ) ) {
                        $suppressLogPage = new LogPage( 'suppress' );
                        $output->addHTML( "<h2>" . $suppressLogPage->getName()->escaped() . "</h2>\n" );
                        LogEventsList::showLogExtract(
@@ -267,7 +279,10 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                                        [ 'action' => 'history' ]
                                );
                                # Link to deleted edits
-                               if ( $this->getUser()->isAllowed( 'undelete' ) ) {
+                               if ( MediaWikiServices::getInstance()
+                                               ->getPermissionManager()
+                                               ->userHasRight( $this->getUser(), 'undelete' )
+                               ) {
                                        $undelete = SpecialPage::getTitleFor( 'Undelete' );
                                        $links[] = $linkRenderer->makeKnownLink(
                                                $undelete,
@@ -471,7 +486,10 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                                Xml::closeElement( 'fieldset' ) . "\n" .
                                Xml::closeElement( 'form' ) . "\n";
                        // Show link to edit the dropdown reasons
-                       if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
+                       if ( MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $this->getUser(), 'editinterface' )
+                       ) {
                                $link = $this->getLinkRenderer()->makeKnownLink(
                                        $this->msg( 'revdelete-reason-dropdown' )->inContentLanguage()->getTitle(),
                                        $this->msg( 'revdelete-edit-reasonlist' )->text(),
@@ -497,7 +515,10 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                        'revdelete-text-others'
                );
 
-               if ( $this->getUser()->isAllowed( 'suppressrevision' ) ) {
+               if ( MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'suppressrevision' )
+               ) {
                        $this->getOutput()->addWikiMsg( 'revdelete-suppress-text' );
                }
 
@@ -602,7 +623,9 @@ class SpecialRevisionDelete extends UnlistedSpecialPage {
                }
                # Can the user set this field?
                if ( $bitParams[RevisionRecord::DELETED_RESTRICTED] == 1
-                       && !$this->getUser()->isAllowed( 'suppressrevision' )
+                       && !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'suppressrevision' )
                ) {
                        throw new PermissionsError( 'suppressrevision' );
                }
index 375694b..530c580 100644 (file)
@@ -52,7 +52,8 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                }
 
                // Validate request parameters
-               $optional = [ 'maxjobs' => 0, 'maxtime' => 30, 'type' => false, 'async' => true ];
+               $optional = [ 'maxjobs' => 0, 'maxtime' => 30, 'type' => false,
+                       'async' => true, 'stats' => false ];
                $required = array_flip( [ 'title', 'tasks', 'signature', 'sigexpiry' ] );
                $params = array_intersect_key( $this->getRequest()->getValues(), $required + $optional );
                $missing = array_diff_key( $required, $params );
@@ -95,14 +96,20 @@ class SpecialRunJobs extends UnlistedSpecialPage {
                                DeferredUpdates::POSTSEND
                        );
                } else {
-                       $this->doRun( $params );
-                       print "Done\n";
+                       $stats = $this->doRun( $params );
+
+                       if ( $params['stats'] ) {
+                               $this->getRequest()->response()->header( 'Content-Type: application/json' );
+                               print FormatJson::encode( $stats );
+                       } else {
+                               print "Done\n";
+                       }
                }
        }
 
        protected function doRun( array $params ) {
                $runner = new JobRunner( LoggerFactory::getInstance( 'runJobs' ) );
-               $runner->run( [
+               return $runner->run( [
                        'type'     => $params['type'],
                        'maxJobs'  => $params['maxjobs'] ?: 1,
                        'maxTime'  => $params['maxtime'] ?: 30
diff --git a/includes/specials/SpecialShortPages.php b/includes/specials/SpecialShortPages.php
new file mode 100644 (file)
index 0000000..f1bd065
--- /dev/null
@@ -0,0 +1,182 @@
+<?php
+/**
+ * Implements Special:Shortpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
+
+/**
+ * SpecialShortpages extends QueryPage. It is used to return the shortest
+ * pages in the database.
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialShortPages extends QueryPage {
+
+       function __construct( $name = 'Shortpages' ) {
+               parent::__construct( $name );
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       public function getQueryInfo() {
+               $config = $this->getConfig();
+               $blacklist = $config->get( 'ShortPagesNamespaceBlacklist' );
+               $tables = [ 'page' ];
+               $conds = [
+                       'page_namespace' => array_diff(
+                               MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces(),
+                               $blacklist
+                       ),
+                       'page_is_redirect' => 0
+               ];
+               $joinConds = [];
+               $options = [ 'USE INDEX' => [ 'page' => 'page_redirect_namespace_len' ] ];
+
+               // Allow extensions to modify the query
+               Hooks::run( 'ShortPagesQuery', [ &$tables, &$conds, &$joinConds, &$options ] );
+
+               return [
+                       'tables' => $tables,
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_len'
+                       ],
+                       'conds' => $conds,
+                       'join_conds' => $joinConds,
+                       'options' => $options
+               ];
+       }
+
+       public function reallyDoQuery( $limit, $offset = false ) {
+               $fname = static::class . '::reallyDoQuery';
+               $dbr = $this->getRecacheDB();
+               $query = $this->getQueryInfo();
+               $order = $this->getOrderFields();
+
+               if ( $this->sortDescending() ) {
+                       foreach ( $order as &$field ) {
+                               $field .= ' DESC';
+                       }
+               }
+
+               $tables = isset( $query['tables'] ) ? (array)$query['tables'] : [];
+               $fields = isset( $query['fields'] ) ? (array)$query['fields'] : [];
+               $conds = isset( $query['conds'] ) ? (array)$query['conds'] : [];
+               $options = isset( $query['options'] ) ? (array)$query['options'] : [];
+               $join_conds = isset( $query['join_conds'] ) ? (array)$query['join_conds'] : [];
+
+               if ( $limit !== false ) {
+                       $options['LIMIT'] = intval( $limit );
+               }
+
+               if ( $offset !== false ) {
+                       $options['OFFSET'] = intval( $offset );
+               }
+
+               $namespaces = $conds['page_namespace'];
+               if ( count( $namespaces ) === 1 ) {
+                       $options['ORDER BY'] = $order;
+                       $res = $dbr->select( $tables, $fields, $conds, $fname,
+                               $options, $join_conds
+                       );
+               } else {
+                       unset( $conds['page_namespace'] );
+                       $options['INNER ORDER BY'] = $order;
+                       $options['ORDER BY'] = [ 'value' . ( $this->sortDescending() ? ' DESC' : '' ) ];
+                       $sql = $dbr->unionConditionPermutations(
+                               $tables,
+                               $fields,
+                               [ 'page_namespace' => $namespaces ],
+                               $conds,
+                               $fname,
+                               $options,
+                               $join_conds
+                       );
+                       $res = $dbr->query( $sql, $fname );
+               }
+
+               return $res;
+       }
+
+       function getOrderFields() {
+               return [ 'page_len' ];
+       }
+
+       /**
+        * @param IDatabase $db
+        * @param IResultWrapper $res
+        */
+       function preprocessResults( $db, $res ) {
+               $this->executeLBFromResultWrapper( $res );
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $dm = $this->getLanguage()->getDirMark();
+
+               $title = Title::makeTitleSafe( $result->namespace, $result->title );
+               if ( !$title ) {
+                       return Html::element( 'span', [ 'class' => 'mw-invalidtitle' ],
+                               Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) );
+               }
+
+               $linkRenderer = $this->getLinkRenderer();
+               $hlink = $linkRenderer->makeKnownLink(
+                       $title,
+                       $this->msg( 'hist' )->text(),
+                       [],
+                       [ 'action' => 'history' ]
+               );
+               $hlinkInParentheses = $this->msg( 'parentheses' )->rawParams( $hlink )->escaped();
+
+               if ( $this->isCached() ) {
+                       $plink = $linkRenderer->makeLink( $title );
+                       $exists = $title->exists();
+               } else {
+                       $plink = $linkRenderer->makeKnownLink( $title );
+                       $exists = true;
+               }
+
+               $size = $this->msg( 'nbytes' )->numParams( $result->value )->escaped();
+
+               return $exists
+                       ? "${hlinkInParentheses} {$dm}{$plink} {$dm}[{$size}]"
+                       : "<del>${hlinkInParentheses} {$dm}{$plink} {$dm}[{$size}]</del>";
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialShortpages.php b/includes/specials/SpecialShortpages.php
deleted file mode 100644 (file)
index 94da25d..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-<?php
-/**
- * Implements Special:Shortpages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\IResultWrapper;
-use Wikimedia\Rdbms\IDatabase;
-
-/**
- * SpecialShortpages extends QueryPage. It is used to return the shortest
- * pages in the database.
- *
- * @ingroup SpecialPage
- */
-class ShortPagesPage extends QueryPage {
-
-       function __construct( $name = 'Shortpages' ) {
-               parent::__construct( $name );
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       public function getQueryInfo() {
-               $config = $this->getConfig();
-               $blacklist = $config->get( 'ShortPagesNamespaceBlacklist' );
-               $tables = [ 'page' ];
-               $conds = [
-                       'page_namespace' => array_diff(
-                               MediaWikiServices::getInstance()->getNamespaceInfo()->getContentNamespaces(),
-                               $blacklist
-                       ),
-                       'page_is_redirect' => 0
-               ];
-               $joinConds = [];
-               $options = [ 'USE INDEX' => [ 'page' => 'page_redirect_namespace_len' ] ];
-
-               // Allow extensions to modify the query
-               Hooks::run( 'ShortPagesQuery', [ &$tables, &$conds, &$joinConds, &$options ] );
-
-               return [
-                       'tables' => $tables,
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_len'
-                       ],
-                       'conds' => $conds,
-                       'join_conds' => $joinConds,
-                       'options' => $options
-               ];
-       }
-
-       public function reallyDoQuery( $limit, $offset = false ) {
-               $fname = static::class . '::reallyDoQuery';
-               $dbr = $this->getRecacheDB();
-               $query = $this->getQueryInfo();
-               $order = $this->getOrderFields();
-
-               if ( $this->sortDescending() ) {
-                       foreach ( $order as &$field ) {
-                               $field .= ' DESC';
-                       }
-               }
-
-               $tables = isset( $query['tables'] ) ? (array)$query['tables'] : [];
-               $fields = isset( $query['fields'] ) ? (array)$query['fields'] : [];
-               $conds = isset( $query['conds'] ) ? (array)$query['conds'] : [];
-               $options = isset( $query['options'] ) ? (array)$query['options'] : [];
-               $join_conds = isset( $query['join_conds'] ) ? (array)$query['join_conds'] : [];
-
-               if ( $limit !== false ) {
-                       $options['LIMIT'] = intval( $limit );
-               }
-
-               if ( $offset !== false ) {
-                       $options['OFFSET'] = intval( $offset );
-               }
-
-               $namespaces = $conds['page_namespace'];
-               if ( count( $namespaces ) === 1 ) {
-                       $options['ORDER BY'] = $order;
-                       $res = $dbr->select( $tables, $fields, $conds, $fname,
-                               $options, $join_conds
-                       );
-               } else {
-                       unset( $conds['page_namespace'] );
-                       $options['INNER ORDER BY'] = $order;
-                       $options['ORDER BY'] = [ 'value' . ( $this->sortDescending() ? ' DESC' : '' ) ];
-                       $sql = $dbr->unionConditionPermutations(
-                               $tables,
-                               $fields,
-                               [ 'page_namespace' => $namespaces ],
-                               $conds,
-                               $fname,
-                               $options,
-                               $join_conds
-                       );
-                       $res = $dbr->query( $sql, $fname );
-               }
-
-               return $res;
-       }
-
-       function getOrderFields() {
-               return [ 'page_len' ];
-       }
-
-       /**
-        * @param IDatabase $db
-        * @param IResultWrapper $res
-        */
-       function preprocessResults( $db, $res ) {
-               $this->executeLBFromResultWrapper( $res );
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $dm = $this->getLanguage()->getDirMark();
-
-               $title = Title::makeTitleSafe( $result->namespace, $result->title );
-               if ( !$title ) {
-                       return Html::element( 'span', [ 'class' => 'mw-invalidtitle' ],
-                               Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) );
-               }
-
-               $linkRenderer = $this->getLinkRenderer();
-               $hlink = $linkRenderer->makeKnownLink(
-                       $title,
-                       $this->msg( 'hist' )->text(),
-                       [],
-                       [ 'action' => 'history' ]
-               );
-               $hlinkInParentheses = $this->msg( 'parentheses' )->rawParams( $hlink )->escaped();
-
-               if ( $this->isCached() ) {
-                       $plink = $linkRenderer->makeLink( $title );
-                       $exists = $title->exists();
-               } else {
-                       $plink = $linkRenderer->makeKnownLink( $title );
-                       $exists = true;
-               }
-
-               $size = $this->msg( 'nbytes' )->numParams( $result->value )->escaped();
-
-               return $exists
-                       ? "${hlinkInParentheses} {$dm}{$plink} {$dm}[{$size}]"
-                       : "<del>${hlinkInParentheses} {$dm}{$plink} {$dm}[{$size}]</del>";
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
index 9a95249..2c8d432 100644 (file)
@@ -21,6 +21,8 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * A special page that lists tags for edits
  *
@@ -77,9 +79,10 @@ class SpecialTags extends SpecialPage {
                $out->wrapWikiMsg( "<div class='mw-tags-intro'>\n$1\n</div>", 'tags-intro' );
 
                $user = $this->getUser();
-               $userCanManage = $user->isAllowed( 'managechangetags' );
-               $userCanDelete = $user->isAllowed( 'deletechangetags' );
-               $userCanEditInterface = $user->isAllowed( 'editinterface' );
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               $userCanManage = $permissionManager->userHasRight( $user, 'managechangetags' );
+               $userCanDelete = $permissionManager->userHasRight( $user, 'deletechangetags' );
+               $userCanEditInterface = $permissionManager->userHasRight( $user, 'editinterface' );
 
                // Show form to create a tag
                if ( $userCanManage ) {
@@ -329,7 +332,9 @@ class SpecialTags extends SpecialPage {
 
        protected function showDeleteTagForm( $tag ) {
                $user = $this->getUser();
-               if ( !$user->isAllowed( 'deletechangetags' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'deletechangetags' ) ) {
                        throw new PermissionsError( 'deletechangetags' );
                }
 
@@ -388,7 +393,9 @@ class SpecialTags extends SpecialPage {
                $actionStr = $activate ? 'activate' : 'deactivate';
 
                $user = $this->getUser();
-               if ( !$user->isAllowed( 'managechangetags' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'managechangetags' ) ) {
                        throw new PermissionsError( 'managechangetags' );
                }
 
index 9b8022b..931b179 100644 (file)
@@ -22,6 +22,7 @@
  */
 
 use MediaWiki\Block\DatabaseBlock;
+use MediaWiki\MediaWikiServices;
 
 /**
  * A special page for unblocking users
@@ -208,7 +209,10 @@ class SpecialUnblock extends SpecialPage {
 
                # If the name was hidden and the blocking user cannot hide
                # names, then don't allow any block removals...
-               if ( !$performer->isAllowed( 'hideuser' ) && $block->getHideName() ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $performer, 'hideuser' ) && $block->getHideName()
+               ) {
                        return [ 'unblock-hideuser' ];
                }
 
diff --git a/includes/specials/SpecialUncategorizedCategories.php b/includes/specials/SpecialUncategorizedCategories.php
new file mode 100644 (file)
index 0000000..7349d95
--- /dev/null
@@ -0,0 +1,94 @@
+<?php
+/**
+ * Implements Special:Uncategorizedcategories
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
+ * A special page that lists uncategorized categories
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialUncategorizedCategories extends SpecialUncategorizedPages {
+       /**
+        * Holds a list of categories, which shouldn't be listed on this special page,
+        * even if it is uncategorized.
+        * @var array
+        */
+       private $exceptionList = null;
+
+       function __construct( $name = 'Uncategorizedcategories' ) {
+               parent::__construct( $name );
+               $this->requestedNamespace = NS_CATEGORY;
+       }
+
+       /**
+        * Returns an array of category titles (usually without the namespace), which
+        * shouldn't be listed on this page, even if they're uncategorized.
+        *
+        * @return array
+        */
+       private function getExceptionList() {
+               if ( $this->exceptionList === null ) {
+                       $this->exceptionList = [];
+                       $exList = $this->msg( 'uncategorized-categories-exceptionlist' )
+                               ->inContentLanguage()->plain();
+                       $proposedTitles = explode( "\n", $exList );
+                       foreach ( $proposedTitles as $count => $titleStr ) {
+                               if ( strpos( $titleStr, '*' ) !== 0 ) {
+                                       continue;
+                               }
+                               $titleStr = preg_replace( "/^\\*\\s*/", '', $titleStr );
+                               $title = Title::newFromText( $titleStr, NS_CATEGORY );
+                               if ( $title && $title->getNamespace() !== NS_CATEGORY ) {
+                                       $title = Title::makeTitleSafe( NS_CATEGORY, $titleStr );
+                               }
+                               if ( $title ) {
+                                       $this->exceptionList[] = $title->getDBkey();
+                               }
+                       }
+               }
+               return $this->exceptionList;
+       }
+
+       public function getQueryInfo() {
+               $dbr = wfGetDB( DB_REPLICA );
+               $query = parent::getQueryInfo();
+               $exceptionList = $this->getExceptionList();
+               if ( $exceptionList ) {
+                       $query['conds'][] = 'page_title not in ( ' . $dbr->makeList( $exceptionList ) . ' )';
+               }
+
+               return $query;
+       }
+
+       /**
+        * Formats the result
+        * @param Skin $skin The current skin
+        * @param object $result The query result
+        * @return string The category link
+        */
+       function formatResult( $skin, $result ) {
+               $title = Title::makeTitle( NS_CATEGORY, $result->title );
+               $text = $title->getText();
+
+               return $this->getLinkRenderer()->makeKnownLink( $title, $text );
+       }
+}
diff --git a/includes/specials/SpecialUncategorizedImages.php b/includes/specials/SpecialUncategorizedImages.php
new file mode 100644 (file)
index 0000000..9dcd1bd
--- /dev/null
@@ -0,0 +1,66 @@
+<?php
+/**
+ * Implements Special:Uncategorizedimages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+/**
+ * Special page lists images which haven't been categorised
+ *
+ * @ingroup SpecialPage
+ * @todo FIXME: Use an instance of UncategorizedPagesPage or something
+ */
+class SpecialUncategorizedImages extends ImageQueryPage {
+       function __construct( $name = 'Uncategorizedimages' ) {
+               parent::__construct( $name );
+               $this->addHelpLink( 'Help:Categories' );
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       function getQueryInfo() {
+               return [
+                       'tables' => [ 'page', 'categorylinks' ],
+                       'fields' => [ 'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_title' ],
+                       'conds' => [ 'cl_from IS NULL',
+                               'page_namespace' => NS_FILE,
+                               'page_is_redirect' => 0 ],
+                       'join_conds' => [ 'categorylinks' => [
+                               'LEFT JOIN', 'cl_from=page_id' ] ]
+               ];
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialUncategorizedPages.php b/includes/specials/SpecialUncategorizedPages.php
new file mode 100644 (file)
index 0000000..3610c01
--- /dev/null
@@ -0,0 +1,93 @@
+<?php
+/**
+ * Implements Special:Uncategorizedpages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * A special page looking for page without any category.
+ *
+ * @ingroup SpecialPage
+ * @todo FIXME: Make $requestedNamespace selectable, unify all subclasses into one
+ */
+class SpecialUncategorizedPages extends PageQueryPage {
+       /** @var int|false */
+       protected $requestedNamespace = false;
+
+       function __construct( $name = 'Uncategorizedpages' ) {
+               parent::__construct( $name );
+               $this->addHelpLink( 'Help:Categories' );
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       function getQueryInfo() {
+               return [
+                       'tables' => [ 'page', 'categorylinks' ],
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_title'
+                       ],
+                       // default for page_namespace is all content namespaces (if requestedNamespace is false)
+                       // otherwise, page_namespace is requestedNamespace
+                       'conds' => [
+                               'cl_from IS NULL',
+                               'page_namespace' => $this->requestedNamespace !== false
+                                               ? $this->requestedNamespace
+                                               : MediaWikiServices::getInstance()->getNamespaceInfo()->
+                                                       getContentNamespaces(),
+                               'page_is_redirect' => 0
+                       ],
+                       'join_conds' => [
+                               'categorylinks' => [ 'LEFT JOIN', 'cl_from = page_id' ]
+                       ]
+               ];
+       }
+
+       function getOrderFields() {
+               // For some crazy reason ordering by a constant
+               // causes a filesort
+               if ( $this->requestedNamespace === false &&
+                       count( MediaWikiServices::getInstance()->getNamespaceInfo()->
+                               getContentNamespaces() ) > 1
+               ) {
+                       return [ 'page_namespace', 'page_title' ];
+               }
+
+               return [ 'page_title' ];
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialUncategorizedTemplates.php b/includes/specials/SpecialUncategorizedTemplates.php
new file mode 100644 (file)
index 0000000..3d6d383
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Implements Special:Uncategorizedtemplates
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+/**
+ * Special page lists all uncategorised pages in the
+ * template namespace
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialUncategorizedTemplates extends SpecialUncategorizedPages {
+       public function __construct( $name = 'Uncategorizedtemplates' ) {
+               parent::__construct( $name );
+               $this->requestedNamespace = NS_TEMPLATE;
+       }
+}
diff --git a/includes/specials/SpecialUncategorizedcategories.php b/includes/specials/SpecialUncategorizedcategories.php
deleted file mode 100644 (file)
index 60cbff1..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-<?php
-/**
- * Implements Special:Uncategorizedcategories
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-/**
- * A special page that lists uncategorized categories
- *
- * @ingroup SpecialPage
- */
-class UncategorizedCategoriesPage extends UncategorizedPagesPage {
-       /**
-        * Holds a list of categories, which shouldn't be listed on this special page,
-        * even if it is uncategorized.
-        * @var array
-        */
-       private $exceptionList = null;
-
-       function __construct( $name = 'Uncategorizedcategories' ) {
-               parent::__construct( $name );
-               $this->requestedNamespace = NS_CATEGORY;
-       }
-
-       /**
-        * Returns an array of category titles (usually without the namespace), which
-        * shouldn't be listed on this page, even if they're uncategorized.
-        *
-        * @return array
-        */
-       private function getExceptionList() {
-               if ( $this->exceptionList === null ) {
-                       $this->exceptionList = [];
-                       $exList = $this->msg( 'uncategorized-categories-exceptionlist' )
-                               ->inContentLanguage()->plain();
-                       $proposedTitles = explode( "\n", $exList );
-                       foreach ( $proposedTitles as $count => $titleStr ) {
-                               if ( strpos( $titleStr, '*' ) !== 0 ) {
-                                       continue;
-                               }
-                               $titleStr = preg_replace( "/^\\*\\s*/", '', $titleStr );
-                               $title = Title::newFromText( $titleStr, NS_CATEGORY );
-                               if ( $title && $title->getNamespace() !== NS_CATEGORY ) {
-                                       $title = Title::makeTitleSafe( NS_CATEGORY, $titleStr );
-                               }
-                               if ( $title ) {
-                                       $this->exceptionList[] = $title->getDBkey();
-                               }
-                       }
-               }
-               return $this->exceptionList;
-       }
-
-       public function getQueryInfo() {
-               $dbr = wfGetDB( DB_REPLICA );
-               $query = parent::getQueryInfo();
-               $exceptionList = $this->getExceptionList();
-               if ( $exceptionList ) {
-                       $query['conds'][] = 'page_title not in ( ' . $dbr->makeList( $exceptionList ) . ' )';
-               }
-
-               return $query;
-       }
-
-       /**
-        * Formats the result
-        * @param Skin $skin The current skin
-        * @param object $result The query result
-        * @return string The category link
-        */
-       function formatResult( $skin, $result ) {
-               $title = Title::makeTitle( NS_CATEGORY, $result->title );
-               $text = $title->getText();
-
-               return $this->getLinkRenderer()->makeKnownLink( $title, $text );
-       }
-}
diff --git a/includes/specials/SpecialUncategorizedimages.php b/includes/specials/SpecialUncategorizedimages.php
deleted file mode 100644 (file)
index ed2d5cf..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-<?php
-/**
- * Implements Special:Uncategorizedimages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>
- */
-
-/**
- * Special page lists images which haven't been categorised
- *
- * @ingroup SpecialPage
- * @todo FIXME: Use an instance of UncategorizedPagesPage or something
- */
-class UncategorizedImagesPage extends ImageQueryPage {
-       function __construct( $name = 'Uncategorizedimages' ) {
-               parent::__construct( $name );
-               $this->addHelpLink( 'Help:Categories' );
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       function getQueryInfo() {
-               return [
-                       'tables' => [ 'page', 'categorylinks' ],
-                       'fields' => [ 'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_title' ],
-                       'conds' => [ 'cl_from IS NULL',
-                               'page_namespace' => NS_FILE,
-                               'page_is_redirect' => 0 ],
-                       'join_conds' => [ 'categorylinks' => [
-                               'LEFT JOIN', 'cl_from=page_id' ] ]
-               ];
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
diff --git a/includes/specials/SpecialUncategorizedpages.php b/includes/specials/SpecialUncategorizedpages.php
deleted file mode 100644 (file)
index 0b7da7b..0000000
+++ /dev/null
@@ -1,93 +0,0 @@
-<?php
-/**
- * Implements Special:Uncategorizedpages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * A special page looking for page without any category.
- *
- * @ingroup SpecialPage
- * @todo FIXME: Make $requestedNamespace selectable, unify all subclasses into one
- */
-class UncategorizedPagesPage extends PageQueryPage {
-       /** @var int|false */
-       protected $requestedNamespace = false;
-
-       function __construct( $name = 'Uncategorizedpages' ) {
-               parent::__construct( $name );
-               $this->addHelpLink( 'Help:Categories' );
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       function getQueryInfo() {
-               return [
-                       'tables' => [ 'page', 'categorylinks' ],
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_title'
-                       ],
-                       // default for page_namespace is all content namespaces (if requestedNamespace is false)
-                       // otherwise, page_namespace is requestedNamespace
-                       'conds' => [
-                               'cl_from IS NULL',
-                               'page_namespace' => $this->requestedNamespace !== false
-                                               ? $this->requestedNamespace
-                                               : MediaWikiServices::getInstance()->getNamespaceInfo()->
-                                                       getContentNamespaces(),
-                               'page_is_redirect' => 0
-                       ],
-                       'join_conds' => [
-                               'categorylinks' => [ 'LEFT JOIN', 'cl_from = page_id' ]
-                       ]
-               ];
-       }
-
-       function getOrderFields() {
-               // For some crazy reason ordering by a constant
-               // causes a filesort
-               if ( $this->requestedNamespace === false &&
-                       count( MediaWikiServices::getInstance()->getNamespaceInfo()->
-                               getContentNamespaces() ) > 1
-               ) {
-                       return [ 'page_namespace', 'page_title' ];
-               }
-
-               return [ 'page_title' ];
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
diff --git a/includes/specials/SpecialUncategorizedtemplates.php b/includes/specials/SpecialUncategorizedtemplates.php
deleted file mode 100644 (file)
index af038fa..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-<?php
-/**
- * Implements Special:Uncategorizedtemplates
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>
- */
-
-/**
- * Special page lists all uncategorised pages in the
- * template namespace
- *
- * @ingroup SpecialPage
- */
-class UncategorizedTemplatesPage extends UncategorizedPagesPage {
-       public function __construct( $name = 'Uncategorizedtemplates' ) {
-               parent::__construct( $name );
-               $this->requestedNamespace = NS_TEMPLATE;
-       }
-}
index 075b5df..d3d3bd7 100644 (file)
@@ -33,18 +33,28 @@ use Wikimedia\Rdbms\IResultWrapper;
  * @ingroup SpecialPage
  */
 class SpecialUndelete extends SpecialPage {
-       private $mAction;
-       private $mTarget;
-       private $mTimestamp;
-       private $mRestore;
-       private $mRevdel;
-       private $mInvert;
-       private $mFilename;
-       private $mTargetTimestamp;
-       private $mAllowed;
-       private $mCanView;
-       private $mComment;
-       private $mToken;
+       private $mAction;
+       private $mTarget;
+       private $mTimestamp;
+       private $mRestore;
+       private $mRevdel;
+       private $mInvert;
+       private $mFilename;
+       private $mTargetTimestamp;
+       private $mAllowed;
+       private $mCanView;
+       private $mComment;
+       private $mToken;
+       /** @var bool|null */
+       private $mPreview;
+       /** @var bool|null */
+       private $mDiff;
+       /** @var bool|null */
+       private $mDiffOnly;
+       /** @var bool|null */
+       private $mUnsuppress;
+       /** @var int[]|null */
+       private $mFileVersions;
 
        /** @var Title */
        private $mTargetObj;
@@ -92,7 +102,9 @@ class SpecialUndelete extends SpecialPage {
                $this->mDiff = $request->getCheck( 'diff' );
                $this->mDiffOnly = $request->getBool( 'diffonly', $this->getUser()->getOption( 'diffonly' ) );
                $this->mComment = $request->getText( 'wpComment' );
-               $this->mUnsuppress = $request->getVal( 'wpUnsuppress' ) && $user->isAllowed( 'suppressrevision' );
+               $this->mUnsuppress = $request->getVal( 'wpUnsuppress' ) && MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'suppressrevision' );
                $this->mToken = $request->getVal( 'token' );
 
                $block = $user->getBlock();
@@ -143,7 +155,7 @@ class SpecialUndelete extends SpecialPage {
                if ( $this->mTargetObj !== null ) {
                        return $permissionManager->userCan( $permission, $user, $this->mTargetObj );
                } else {
-                       return $user->isAllowed( $permission );
+                       return $permissionManager->userHasRight( $user, $permission );
                }
        }
 
@@ -169,7 +181,10 @@ class SpecialUndelete extends SpecialPage {
                        $out->addWikiMsg( 'undelete-header' );
 
                        # Not all users can just browse every deleted page from the list
-                       if ( $user->isAllowed( 'browsearchive' ) ) {
+                       if ( MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $user, 'browsearchive' )
+                       ) {
                                $this->showSearchForm();
                        }
 
@@ -764,7 +779,8 @@ class SpecialUndelete extends SpecialPage {
                LogEventsList::showLogExtract( $out, 'delete', $this->mTargetObj );
                # Show relevant lines from the suppression log:
                $suppressLogPage = new LogPage( 'suppress' );
-               if ( $this->getUser()->isAllowed( 'suppressionlog' ) ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( $permissionManager->userHasRight( $this->getUser(), 'suppressionlog' ) ) {
                        $out->addHTML( Xml::element( 'h2', null, $suppressLogPage->getName()->text() ) . "\n" );
                        LogEventsList::showLogExtract( $out, 'suppress', $this->mTargetObj );
                }
@@ -816,7 +832,7 @@ class SpecialUndelete extends SpecialPage {
                                ] )
                        );
 
-                       if ( $this->getUser()->isAllowed( 'suppressrevision' ) ) {
+                       if ( $permissionManager->userHasRight( $this->getUser(), 'suppressrevision' ) ) {
                                $fields[] = new OOUI\FieldLayout(
                                        new OOUI\CheckboxInputWidget( [
                                                'name' => 'wpUnsuppress',
@@ -856,7 +872,7 @@ class SpecialUndelete extends SpecialPage {
                if ( $haveRevisions ) {
                        # Show the page's stored (deleted) history
 
-                       if ( $this->getUser()->isAllowed( 'deleterevision' ) ) {
+                       if ( $permissionManager->userHasRight( $this->getUser(), 'deleterevision' ) ) {
                                $history .= Html::element(
                                        'button',
                                        [
diff --git a/includes/specials/SpecialUnusedCategories.php b/includes/specials/SpecialUnusedCategories.php
new file mode 100644 (file)
index 0000000..36367d2
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Implements Special:Unusedcategories
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
+ * @ingroup SpecialPage
+ */
+class SpecialUnusedCategories extends QueryPage {
+       function __construct( $name = 'Unusedcategories' ) {
+               parent::__construct( $name );
+       }
+
+       public function isExpensive() {
+               return true;
+       }
+
+       function getPageHeader() {
+               return $this->msg( 'unusedcategoriestext' )->parseAsBlock();
+       }
+
+       public function getQueryInfo() {
+               return [
+                       'tables' => [ 'page', 'categorylinks', 'page_props' ],
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_title'
+                       ],
+                       'conds' => [
+                               'cl_from IS NULL',
+                               'page_namespace' => NS_CATEGORY,
+                               'page_is_redirect' => 0,
+                               'pp_page IS NULL'
+                       ],
+                       'join_conds' => [
+                               'categorylinks' => [ 'LEFT JOIN', 'cl_to = page_title' ],
+                               'page_props' => [ 'LEFT JOIN', [
+                                       'page_id = pp_page',
+                                       'pp_propname' => 'expectunusedcategory'
+                               ] ]
+                       ]
+               ];
+       }
+
+       /**
+        * A should come before Z (T32907)
+        * @return bool
+        */
+       function sortDescending() {
+               return false;
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $title = Title::makeTitle( NS_CATEGORY, $result->title );
+
+               return $this->getLinkRenderer()->makeLink( $title, $title->getText() );
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+
+       public function preprocessResults( $db, $res ) {
+               $this->executeLBFromResultWrapper( $res );
+       }
+}
diff --git a/includes/specials/SpecialUnusedImages.php b/includes/specials/SpecialUnusedImages.php
new file mode 100644 (file)
index 0000000..cb215e3
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Implements Special:Unusedimages
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+/**
+ * A special page that lists unused images
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialUnusedImages extends ImageQueryPage {
+       function __construct( $name = 'Unusedimages' ) {
+               parent::__construct( $name );
+       }
+
+       function isExpensive() {
+               return true;
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       function getQueryInfo() {
+               $retval = [
+                       'tables' => [ 'image', 'imagelinks' ],
+                       'fields' => [
+                               'namespace' => NS_FILE,
+                               'title' => 'img_name',
+                               'value' => 'img_timestamp',
+                       ],
+                       'conds' => [ 'il_to IS NULL' ],
+                       'join_conds' => [ 'imagelinks' => [ 'LEFT JOIN', 'il_to = img_name' ] ]
+               ];
+
+               if ( $this->getConfig()->get( 'CountCategorizedImagesAsUsed' ) ) {
+                       // Order is significant
+                       $retval['tables'] = [ 'image', 'page', 'categorylinks',
+                               'imagelinks' ];
+                       $retval['conds']['page_namespace'] = NS_FILE;
+                       $retval['conds'][] = 'cl_from IS NULL';
+                       $retval['conds'][] = 'img_name = page_title';
+                       $retval['join_conds']['categorylinks'] = [
+                               'LEFT JOIN', 'cl_from = page_id' ];
+                       $retval['join_conds']['imagelinks'] = [
+                               'LEFT JOIN', 'il_to = page_title' ];
+               }
+
+               return $retval;
+       }
+
+       function usesTimestamps() {
+               return true;
+       }
+
+       function getPageHeader() {
+               if ( $this->getConfig()->get( 'CountCategorizedImagesAsUsed' ) ) {
+                       return $this->msg(
+                               'unusedimagestext-categorizedimgisused'
+                       )->parseAsBlock();
+               }
+               return $this->msg( 'unusedimagestext' )->parseAsBlock();
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialUnusedTemplates.php b/includes/specials/SpecialUnusedTemplates.php
new file mode 100644 (file)
index 0000000..119ef87
--- /dev/null
@@ -0,0 +1,97 @@
+<?php
+/**
+ * Implements Special:Unusedtemplates
+ *
+ * Copyright © 2006 Rob Church
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+/**
+ * A special page that lists unused templates
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialUnusedTemplates extends QueryPage {
+       function __construct( $name = 'Unusedtemplates' ) {
+               parent::__construct( $name );
+       }
+
+       public function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       public function getQueryInfo() {
+               return [
+                       'tables' => [ 'page', 'templatelinks' ],
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_title'
+                       ],
+                       'conds' => [
+                               'page_namespace' => NS_TEMPLATE,
+                               'tl_from IS NULL',
+                               'page_is_redirect' => 0
+                       ],
+                       'join_conds' => [ 'templatelinks' => [
+                               'LEFT JOIN', [ 'tl_title = page_title',
+                                       'tl_namespace = page_namespace' ] ] ]
+               ];
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $linkRenderer = $this->getLinkRenderer();
+               $title = Title::makeTitle( NS_TEMPLATE, $result->title );
+               $pageLink = $linkRenderer->makeKnownLink(
+                       $title,
+                       null,
+                       [],
+                       [ 'redirect' => 'no' ]
+               );
+               $wlhLink = $linkRenderer->makeKnownLink(
+                       SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedText() ),
+                       $this->msg( 'unusedtemplateswlh' )->text()
+               );
+
+               return $this->getLanguage()->specialList( $pageLink, $wlhLink );
+       }
+
+       function getPageHeader() {
+               return $this->msg( 'unusedtemplatestext' )->parseAsBlock();
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialUnusedcategories.php b/includes/specials/SpecialUnusedcategories.php
deleted file mode 100644 (file)
index 2577a10..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * Implements Special:Unusedcategories
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-/**
- * @ingroup SpecialPage
- */
-class UnusedCategoriesPage extends QueryPage {
-       function __construct( $name = 'Unusedcategories' ) {
-               parent::__construct( $name );
-       }
-
-       public function isExpensive() {
-               return true;
-       }
-
-       function getPageHeader() {
-               return $this->msg( 'unusedcategoriestext' )->parseAsBlock();
-       }
-
-       public function getQueryInfo() {
-               return [
-                       'tables' => [ 'page', 'categorylinks', 'page_props' ],
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_title'
-                       ],
-                       'conds' => [
-                               'cl_from IS NULL',
-                               'page_namespace' => NS_CATEGORY,
-                               'page_is_redirect' => 0,
-                               'pp_page IS NULL'
-                       ],
-                       'join_conds' => [
-                               'categorylinks' => [ 'LEFT JOIN', 'cl_to = page_title' ],
-                               'page_props' => [ 'LEFT JOIN', [
-                                       'page_id = pp_page',
-                                       'pp_propname' => 'expectunusedcategory'
-                               ] ]
-                       ]
-               ];
-       }
-
-       /**
-        * A should come before Z (T32907)
-        * @return bool
-        */
-       function sortDescending() {
-               return false;
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $title = Title::makeTitle( NS_CATEGORY, $result->title );
-
-               return $this->getLinkRenderer()->makeLink( $title, $title->getText() );
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-
-       public function preprocessResults( $db, $res ) {
-               $this->executeLBFromResultWrapper( $res );
-       }
-}
diff --git a/includes/specials/SpecialUnusedimages.php b/includes/specials/SpecialUnusedimages.php
deleted file mode 100644 (file)
index bcb3b85..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-<?php
-/**
- * Implements Special:Unusedimages
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-/**
- * A special page that lists unused images
- *
- * @ingroup SpecialPage
- */
-class UnusedimagesPage extends ImageQueryPage {
-       function __construct( $name = 'Unusedimages' ) {
-               parent::__construct( $name );
-       }
-
-       function isExpensive() {
-               return true;
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       function getQueryInfo() {
-               $retval = [
-                       'tables' => [ 'image', 'imagelinks' ],
-                       'fields' => [
-                               'namespace' => NS_FILE,
-                               'title' => 'img_name',
-                               'value' => 'img_timestamp',
-                       ],
-                       'conds' => [ 'il_to IS NULL' ],
-                       'join_conds' => [ 'imagelinks' => [ 'LEFT JOIN', 'il_to = img_name' ] ]
-               ];
-
-               if ( $this->getConfig()->get( 'CountCategorizedImagesAsUsed' ) ) {
-                       // Order is significant
-                       $retval['tables'] = [ 'image', 'page', 'categorylinks',
-                               'imagelinks' ];
-                       $retval['conds']['page_namespace'] = NS_FILE;
-                       $retval['conds'][] = 'cl_from IS NULL';
-                       $retval['conds'][] = 'img_name = page_title';
-                       $retval['join_conds']['categorylinks'] = [
-                               'LEFT JOIN', 'cl_from = page_id' ];
-                       $retval['join_conds']['imagelinks'] = [
-                               'LEFT JOIN', 'il_to = page_title' ];
-               }
-
-               return $retval;
-       }
-
-       function usesTimestamps() {
-               return true;
-       }
-
-       function getPageHeader() {
-               if ( $this->getConfig()->get( 'CountCategorizedImagesAsUsed' ) ) {
-                       return $this->msg(
-                               'unusedimagestext-categorizedimgisused'
-                       )->parseAsBlock();
-               }
-               return $this->msg( 'unusedimagestext' )->parseAsBlock();
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
diff --git a/includes/specials/SpecialUnusedtemplates.php b/includes/specials/SpecialUnusedtemplates.php
deleted file mode 100644 (file)
index f73be43..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-<?php
-/**
- * Implements Special:Unusedtemplates
- *
- * Copyright © 2006 Rob Church
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>
- */
-
-/**
- * A special page that lists unused templates
- *
- * @ingroup SpecialPage
- */
-class UnusedtemplatesPage extends QueryPage {
-       function __construct( $name = 'Unusedtemplates' ) {
-               parent::__construct( $name );
-       }
-
-       public function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       public function getQueryInfo() {
-               return [
-                       'tables' => [ 'page', 'templatelinks' ],
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_title'
-                       ],
-                       'conds' => [
-                               'page_namespace' => NS_TEMPLATE,
-                               'tl_from IS NULL',
-                               'page_is_redirect' => 0
-                       ],
-                       'join_conds' => [ 'templatelinks' => [
-                               'LEFT JOIN', [ 'tl_title = page_title',
-                                       'tl_namespace = page_namespace' ] ] ]
-               ];
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $linkRenderer = $this->getLinkRenderer();
-               $title = Title::makeTitle( NS_TEMPLATE, $result->title );
-               $pageLink = $linkRenderer->makeKnownLink(
-                       $title,
-                       null,
-                       [],
-                       [ 'redirect' => 'no' ]
-               );
-               $wlhLink = $linkRenderer->makeKnownLink(
-                       SpecialPage::getTitleFor( 'Whatlinkshere', $title->getPrefixedText() ),
-                       $this->msg( 'unusedtemplateswlh' )->text()
-               );
-
-               return $this->getLanguage()->specialList( $pageLink, $wlhLink );
-       }
-
-       function getPageHeader() {
-               return $this->msg( 'unusedtemplatestext' )->parseAsBlock();
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
diff --git a/includes/specials/SpecialUnwatchedPages.php b/includes/specials/SpecialUnwatchedPages.php
new file mode 100644 (file)
index 0000000..42adaa0
--- /dev/null
@@ -0,0 +1,139 @@
+<?php
+/**
+ * Implements Special:Unwatchedpages
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ */
+
+use MediaWiki\MediaWikiServices;
+use Wikimedia\Rdbms\IResultWrapper;
+use Wikimedia\Rdbms\IDatabase;
+
+/**
+ * A special page that displays a list of pages that are not on anyones watchlist.
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialUnwatchedPages extends QueryPage {
+
+       function __construct( $name = 'Unwatchedpages' ) {
+               parent::__construct( $name, 'unwatchedpages' );
+       }
+
+       public function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       /**
+        * Pre-cache page existence to speed up link generation
+        *
+        * @param IDatabase $db
+        * @param IResultWrapper $res
+        */
+       public function preprocessResults( $db, $res ) {
+               if ( !$res->numRows() ) {
+                       return;
+               }
+
+               $batch = new LinkBatch();
+               foreach ( $res as $row ) {
+                       $batch->add( $row->namespace, $row->title );
+               }
+               $batch->execute();
+
+               $res->seek( 0 );
+       }
+
+       public function getQueryInfo() {
+               $dbr = wfGetDB( DB_REPLICA );
+               return [
+                       'tables' => [ 'page', 'watchlist' ],
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_namespace'
+                       ],
+                       'conds' => [
+                               'wl_title IS NULL',
+                               'page_is_redirect' => 0,
+                               'page_namespace != ' . $dbr->addQuotes( NS_MEDIAWIKI ),
+                       ],
+                       'join_conds' => [ 'watchlist' => [
+                               'LEFT JOIN', [ 'wl_title = page_title',
+                                       'wl_namespace = page_namespace' ] ] ]
+               ];
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       function getOrderFields() {
+               return [ 'page_namespace', 'page_title' ];
+       }
+
+       /**
+        * Add the JS
+        * @param string|null $par
+        */
+       public function execute( $par ) {
+               parent::execute( $par );
+               $this->getOutput()->addModules( 'mediawiki.special.unwatchedPages' );
+               $this->addHelpLink( 'Help:Watchlist' );
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $nt = Title::makeTitleSafe( $result->namespace, $result->title );
+               if ( !$nt ) {
+                       return Html::element( 'span', [ 'class' => 'mw-invalidtitle' ],
+                               Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) );
+               }
+
+               $text = MediaWikiServices::getInstance()->getContentLanguage()->
+                       convert( htmlspecialchars( $nt->getPrefixedText() ) );
+
+               $linkRenderer = $this->getLinkRenderer();
+
+               $plink = $linkRenderer->makeKnownLink( $nt, new HtmlArmor( $text ) );
+               $wlink = $linkRenderer->makeKnownLink(
+                       $nt,
+                       $this->msg( 'watch' )->text(),
+                       [ 'class' => 'mw-watch-link' ],
+                       [ 'action' => 'watch' ]
+               );
+
+               return $this->getLanguage()->specialList( $plink, $wlink );
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialUnwatchedpages.php b/includes/specials/SpecialUnwatchedpages.php
deleted file mode 100644 (file)
index 3c5de64..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-<?php
-/**
- * Implements Special:Unwatchedpages
- *
- * Copyright © 2005 Ævar Arnfjörð Bjarmason
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- */
-
-use MediaWiki\MediaWikiServices;
-use Wikimedia\Rdbms\IResultWrapper;
-use Wikimedia\Rdbms\IDatabase;
-
-/**
- * A special page that displays a list of pages that are not on anyones watchlist.
- *
- * @ingroup SpecialPage
- */
-class UnwatchedpagesPage extends QueryPage {
-
-       function __construct( $name = 'Unwatchedpages' ) {
-               parent::__construct( $name, 'unwatchedpages' );
-       }
-
-       public function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       /**
-        * Pre-cache page existence to speed up link generation
-        *
-        * @param IDatabase $db
-        * @param IResultWrapper $res
-        */
-       public function preprocessResults( $db, $res ) {
-               if ( !$res->numRows() ) {
-                       return;
-               }
-
-               $batch = new LinkBatch();
-               foreach ( $res as $row ) {
-                       $batch->add( $row->namespace, $row->title );
-               }
-               $batch->execute();
-
-               $res->seek( 0 );
-       }
-
-       public function getQueryInfo() {
-               $dbr = wfGetDB( DB_REPLICA );
-               return [
-                       'tables' => [ 'page', 'watchlist' ],
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_namespace'
-                       ],
-                       'conds' => [
-                               'wl_title IS NULL',
-                               'page_is_redirect' => 0,
-                               'page_namespace != ' . $dbr->addQuotes( NS_MEDIAWIKI ),
-                       ],
-                       'join_conds' => [ 'watchlist' => [
-                               'LEFT JOIN', [ 'wl_title = page_title',
-                                       'wl_namespace = page_namespace' ] ] ]
-               ];
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       function getOrderFields() {
-               return [ 'page_namespace', 'page_title' ];
-       }
-
-       /**
-        * Add the JS
-        * @param string|null $par
-        */
-       public function execute( $par ) {
-               parent::execute( $par );
-               $this->getOutput()->addModules( 'mediawiki.special.unwatchedPages' );
-               $this->addHelpLink( 'Help:Watchlist' );
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $nt = Title::makeTitleSafe( $result->namespace, $result->title );
-               if ( !$nt ) {
-                       return Html::element( 'span', [ 'class' => 'mw-invalidtitle' ],
-                               Linker::getInvalidTitleDescription( $this->getContext(), $result->namespace, $result->title ) );
-               }
-
-               $text = MediaWikiServices::getInstance()->getContentLanguage()->
-                       convert( htmlspecialchars( $nt->getPrefixedText() ) );
-
-               $linkRenderer = $this->getLinkRenderer();
-
-               $plink = $linkRenderer->makeKnownLink( $nt, new HtmlArmor( $text ) );
-               $wlink = $linkRenderer->makeKnownLink(
-                       $nt,
-                       $this->msg( 'watch' )->text(),
-                       [ 'class' => 'mw-watch-link' ],
-                       [ 'action' => 'watch' ]
-               );
-
-               return $this->getLanguage()->specialList( $plink, $wlink );
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
index 81c9d56..e7c2e42 100644 (file)
@@ -311,16 +311,18 @@ class SpecialUpload extends SpecialPage {
        protected function showViewDeletedLinks() {
                $title = Title::makeTitleSafe( NS_FILE, $this->mDesiredDestName );
                $user = $this->getUser();
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
                // Show a subtitle link to deleted revisions (to sysops et al only)
                if ( $title instanceof Title ) {
                        $count = $title->isDeleted();
-                       if ( $count > 0 && $user->isAllowed( 'deletedhistory' ) ) {
+                       if ( $count > 0 && $permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
                                $restorelink = $this->getLinkRenderer()->makeKnownLink(
                                        SpecialPage::getTitleFor( 'Undelete', $title->getPrefixedText() ),
                                        $this->msg( 'restorelink' )->numParams( $count )->text()
                                );
-                               $link = $this->msg( $user->isAllowed( 'delete' ) ? 'thisisdeleted' : 'viewdeleted' )
-                                       ->rawParams( $restorelink )->parseAsBlock();
+                               $link = $this->msg(
+                                       $permissionManager->userHasRight( $user, 'delete' ) ? 'thisisdeleted' : 'viewdeleted'
+                               )->rawParams( $restorelink )->parseAsBlock();
                                $this->getOutput()->addHTML(
                                        Html::rawElement(
                                                'div',
index 5747f67..585699d 100644 (file)
@@ -21,6 +21,8 @@
  * @ingroup SpecialPage
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * Special page to allow managing user group membership
  *
@@ -161,7 +163,10 @@ class UserrightsPage extends SpecialPage {
                         * (e.g. they don't have the userrights permission), then don't
                         * allow them to change any user rights.
                         */
-                       if ( !$user->isAllowed( 'userrights' ) ) {
+                       if ( !MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $user, 'userrights' )
+                       ) {
                                $block = $user->getBlock();
                                if ( $block && $block->isSitewide() ) {
                                        throw new UserBlockedError( $block );
@@ -515,7 +520,10 @@ class UserrightsPage extends SpecialPage {
                        if ( WikiMap::isCurrentWikiId( $dbDomain ) ) {
                                $dbDomain = '';
                        } else {
-                               if ( $writing && !$this->getUser()->isAllowed( 'userrights-interwiki' ) ) {
+                               if ( $writing && !MediaWikiServices::getInstance()
+                                               ->getPermissionManager()
+                                               ->userHasRight( $this->getUser(), 'userrights-interwiki' )
+                               ) {
                                        return Status::newFatal( 'userrights-no-interwiki' );
                                }
                                if ( !UserRightsProxy::validDatabase( $dbDomain ) ) {
diff --git a/includes/specials/SpecialWantedCategories.php b/includes/specials/SpecialWantedCategories.php
new file mode 100644 (file)
index 0000000..659650c
--- /dev/null
@@ -0,0 +1,130 @@
+<?php
+/**
+ * Implements Special:Wantedcategories
+ *
+ * Copyright © 2005 Ævar Arnfjörð Bjarmason
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * A querypage to list the most wanted categories - implements Special:Wantedcategories
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialWantedCategories extends WantedQueryPage {
+       private $currentCategoryCounts;
+
+       function __construct( $name = 'Wantedcategories' ) {
+               parent::__construct( $name );
+       }
+
+       function getQueryInfo() {
+               return [
+                       'tables' => [ 'categorylinks', 'page' ],
+                       'fields' => [
+                               'namespace' => NS_CATEGORY,
+                               'title' => 'cl_to',
+                               'value' => 'COUNT(*)'
+                       ],
+                       'conds' => [ 'page_title IS NULL' ],
+                       'options' => [ 'GROUP BY' => 'cl_to' ],
+                       'join_conds' => [ 'page' => [ 'LEFT JOIN',
+                               [ 'page_title = cl_to',
+                                       'page_namespace' => NS_CATEGORY ] ] ]
+               ];
+       }
+
+       function preprocessResults( $db, $res ) {
+               parent::preprocessResults( $db, $res );
+
+               $this->currentCategoryCounts = [];
+
+               if ( !$res->numRows() || !$this->isCached() ) {
+                       return;
+               }
+
+               // Fetch (hopefully) up-to-date numbers of pages in each category.
+               // This should be fast enough as we limit the list to a reasonable length.
+
+               $allCategories = [];
+               foreach ( $res as $row ) {
+                       $allCategories[] = $row->title;
+               }
+
+               $categoryRes = $db->select(
+                       'category',
+                       [ 'cat_title', 'cat_pages' ],
+                       [ 'cat_title' => $allCategories ],
+                       __METHOD__
+               );
+               foreach ( $categoryRes as $row ) {
+                       $this->currentCategoryCounts[$row->cat_title] = intval( $row->cat_pages );
+               }
+
+               // Back to start for display
+               $res->seek( 0 );
+       }
+
+       /**
+        * @param Skin $skin
+        * @param object $result Result row
+        * @return string
+        */
+       function formatResult( $skin, $result ) {
+               $nt = Title::makeTitle( $result->namespace, $result->title );
+               $text = new HtmlArmor( MediaWikiServices::getInstance()->getContentLanguage()
+                       ->convert( htmlspecialchars( $nt->getText() ) ) );
+
+               if ( !$this->isCached() ) {
+                       // We can assume the freshest data
+                       $plink = $this->getLinkRenderer()->makeBrokenLink(
+                               $nt,
+                               $text
+                       );
+                       $nlinks = $this->msg( 'nmembers' )->numParams( $result->value )->escaped();
+               } else {
+                       $plink = $this->getLinkRenderer()->makeLink( $nt, $text );
+
+                       $currentValue = $this->currentCategoryCounts[$result->title] ?? 0;
+                       $cachedValue = intval( $result->value ); // T76910
+
+                       // If the category has been created or emptied since the list was refreshed, strike it
+                       if ( $nt->isKnown() || $currentValue === 0 ) {
+                               $plink = "<del>$plink</del>";
+                       }
+
+                       // Show the current number of category entries if it changed
+                       if ( $currentValue !== $cachedValue ) {
+                               $nlinks = $this->msg( 'nmemberschanged' )
+                                       ->numParams( $cachedValue, $currentValue )->escaped();
+                       } else {
+                               $nlinks = $this->msg( 'nmembers' )->numParams( $cachedValue )->escaped();
+                       }
+               }
+
+               return $this->getLanguage()->specialList( $plink, $nlinks );
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialWantedTemplates.php b/includes/specials/SpecialWantedTemplates.php
new file mode 100644 (file)
index 0000000..453f7b8
--- /dev/null
@@ -0,0 +1,61 @@
+<?php
+/**
+ * Implements Special:Wantedtemplates
+ *
+ * Copyright © 2008, Danny B.
+ * Based on SpecialWantedcategories.php by Ævar Arnfjörð Bjarmason <avarab@gmail.com>
+ * makeWlhLink() taken from SpecialMostlinkedtemplates by Rob Church <robchur@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Danny B.
+ */
+
+/**
+ * A querypage to list the most wanted templates
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialWantedTemplates extends WantedQueryPage {
+       function __construct( $name = 'Wantedtemplates' ) {
+               parent::__construct( $name );
+       }
+
+       function getQueryInfo() {
+               return [
+                       'tables' => [ 'templatelinks', 'page' ],
+                       'fields' => [
+                               'namespace' => 'tl_namespace',
+                               'title' => 'tl_title',
+                               'value' => 'COUNT(*)'
+                       ],
+                       'conds' => [
+                               'page_title IS NULL',
+                               'tl_namespace' => NS_TEMPLATE
+                       ],
+                       'options' => [ 'GROUP BY' => [ 'tl_namespace', 'tl_title' ] ],
+                       'join_conds' => [ 'page' => [ 'LEFT JOIN',
+                               [ 'page_namespace = tl_namespace',
+                                       'page_title = tl_title' ] ] ]
+               ];
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialWantedcategories.php b/includes/specials/SpecialWantedcategories.php
deleted file mode 100644 (file)
index 5c62298..0000000
+++ /dev/null
@@ -1,130 +0,0 @@
-<?php
-/**
- * Implements Special:Wantedcategories
- *
- * Copyright © 2005 Ævar Arnfjörð Bjarmason
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * A querypage to list the most wanted categories - implements Special:Wantedcategories
- *
- * @ingroup SpecialPage
- */
-class WantedCategoriesPage extends WantedQueryPage {
-       private $currentCategoryCounts;
-
-       function __construct( $name = 'Wantedcategories' ) {
-               parent::__construct( $name );
-       }
-
-       function getQueryInfo() {
-               return [
-                       'tables' => [ 'categorylinks', 'page' ],
-                       'fields' => [
-                               'namespace' => NS_CATEGORY,
-                               'title' => 'cl_to',
-                               'value' => 'COUNT(*)'
-                       ],
-                       'conds' => [ 'page_title IS NULL' ],
-                       'options' => [ 'GROUP BY' => 'cl_to' ],
-                       'join_conds' => [ 'page' => [ 'LEFT JOIN',
-                               [ 'page_title = cl_to',
-                                       'page_namespace' => NS_CATEGORY ] ] ]
-               ];
-       }
-
-       function preprocessResults( $db, $res ) {
-               parent::preprocessResults( $db, $res );
-
-               $this->currentCategoryCounts = [];
-
-               if ( !$res->numRows() || !$this->isCached() ) {
-                       return;
-               }
-
-               // Fetch (hopefully) up-to-date numbers of pages in each category.
-               // This should be fast enough as we limit the list to a reasonable length.
-
-               $allCategories = [];
-               foreach ( $res as $row ) {
-                       $allCategories[] = $row->title;
-               }
-
-               $categoryRes = $db->select(
-                       'category',
-                       [ 'cat_title', 'cat_pages' ],
-                       [ 'cat_title' => $allCategories ],
-                       __METHOD__
-               );
-               foreach ( $categoryRes as $row ) {
-                       $this->currentCategoryCounts[$row->cat_title] = intval( $row->cat_pages );
-               }
-
-               // Back to start for display
-               $res->seek( 0 );
-       }
-
-       /**
-        * @param Skin $skin
-        * @param object $result Result row
-        * @return string
-        */
-       function formatResult( $skin, $result ) {
-               $nt = Title::makeTitle( $result->namespace, $result->title );
-               $text = new HtmlArmor( MediaWikiServices::getInstance()->getContentLanguage()
-                       ->convert( htmlspecialchars( $nt->getText() ) ) );
-
-               if ( !$this->isCached() ) {
-                       // We can assume the freshest data
-                       $plink = $this->getLinkRenderer()->makeBrokenLink(
-                               $nt,
-                               $text
-                       );
-                       $nlinks = $this->msg( 'nmembers' )->numParams( $result->value )->escaped();
-               } else {
-                       $plink = $this->getLinkRenderer()->makeLink( $nt, $text );
-
-                       $currentValue = $this->currentCategoryCounts[$result->title] ?? 0;
-                       $cachedValue = intval( $result->value ); // T76910
-
-                       // If the category has been created or emptied since the list was refreshed, strike it
-                       if ( $nt->isKnown() || $currentValue === 0 ) {
-                               $plink = "<del>$plink</del>";
-                       }
-
-                       // Show the current number of category entries if it changed
-                       if ( $currentValue !== $cachedValue ) {
-                               $nlinks = $this->msg( 'nmemberschanged' )
-                                       ->numParams( $cachedValue, $currentValue )->escaped();
-                       } else {
-                               $nlinks = $this->msg( 'nmembers' )->numParams( $cachedValue )->escaped();
-                       }
-               }
-
-               return $this->getLanguage()->specialList( $plink, $nlinks );
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
diff --git a/includes/specials/SpecialWantedtemplates.php b/includes/specials/SpecialWantedtemplates.php
deleted file mode 100644 (file)
index 66e6814..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<?php
-/**
- * Implements Special:Wantedtemplates
- *
- * Copyright © 2008, Danny B.
- * Based on SpecialWantedcategories.php by Ævar Arnfjörð Bjarmason <avarab@gmail.com>
- * makeWlhLink() taken from SpecialMostlinkedtemplates by Rob Church <robchur@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Danny B.
- */
-
-/**
- * A querypage to list the most wanted templates
- *
- * @ingroup SpecialPage
- */
-class WantedTemplatesPage extends WantedQueryPage {
-       function __construct( $name = 'Wantedtemplates' ) {
-               parent::__construct( $name );
-       }
-
-       function getQueryInfo() {
-               return [
-                       'tables' => [ 'templatelinks', 'page' ],
-                       'fields' => [
-                               'namespace' => 'tl_namespace',
-                               'title' => 'tl_title',
-                               'value' => 'COUNT(*)'
-                       ],
-                       'conds' => [
-                               'page_title IS NULL',
-                               'tl_namespace' => NS_TEMPLATE
-                       ],
-                       'options' => [ 'GROUP BY' => [ 'tl_namespace', 'tl_title' ] ],
-                       'join_conds' => [ 'page' => [ 'LEFT JOIN',
-                               [ 'page_namespace = tl_namespace',
-                                       'page_title = tl_title' ] ] ]
-               ];
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
index 3d56330..84b3331 100644 (file)
@@ -381,12 +381,10 @@ class SpecialWatchlist extends ChangesListSpecialPage {
 
                // Log entries with DELETED_ACTION must not show up unless the user has
                // the necessary rights.
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( !$permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
                        $bitmask = LogPage::DELETED_ACTION;
-               } elseif ( !MediaWikiServices::getInstance()
-                       ->getPermissionManager()
-                       ->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' )
-               ) {
+               } elseif ( !$permissionManager->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' ) ) {
                        $bitmask = LogPage::DELETED_ACTION | LogPage::DELETED_RESTRICTED;
                } else {
                        $bitmask = 0;
index 2840086..5fe3605 100644 (file)
@@ -21,6 +21,7 @@
  * @todo Use some variant of Pager or something; the pagination here is lousy.
  */
 
+use MediaWiki\MediaWikiServices;
 use Wikimedia\Rdbms\IDatabase;
 
 /**
@@ -416,7 +417,9 @@ class SpecialWhatLinksHere extends IncludableSpecialPage {
                // if the page is editable, add an edit link
                if (
                        // check user permissions
-                       $this->getUser()->isAllowed( 'edit' ) &&
+                       MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'edit' ) &&
                        // check, if the content model is editable through action=edit
                        ContentHandler::getForTitle( $target )->supportsDirectEditing()
                ) {
diff --git a/includes/specials/SpecialWithoutInterwiki.php b/includes/specials/SpecialWithoutInterwiki.php
new file mode 100644 (file)
index 0000000..36aea75
--- /dev/null
@@ -0,0 +1,113 @@
+<?php
+/**
+ * Implements Special:Withoutinterwiki
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ * @ingroup SpecialPage
+ * @author Rob Church <robchur@gmail.com>
+ */
+
+use MediaWiki\MediaWikiServices;
+
+/**
+ * Special page lists pages without language links
+ *
+ * @ingroup SpecialPage
+ */
+class SpecialWithoutInterwiki extends PageQueryPage {
+       private $prefix = '';
+
+       function __construct( $name = 'Withoutinterwiki' ) {
+               parent::__construct( $name );
+       }
+
+       function execute( $par ) {
+               $this->prefix = Title::capitalize(
+                       $this->getRequest()->getVal( 'prefix', $par ), NS_MAIN );
+               parent::execute( $par );
+       }
+
+       function getPageHeader() {
+               # Do not show useless input form if special page is cached
+               if ( $this->isCached() ) {
+                       return '';
+               }
+
+               $formDescriptor = [
+                       'prefix' => [
+                               'label-message' => 'allpagesprefix',
+                               'name' => 'prefix',
+                               'id' => 'wiprefix',
+                               'type' => 'text',
+                               'size' => 20,
+                               'default' => $this->prefix
+                       ]
+               ];
+
+               $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() );
+               $htmlForm->setWrapperLegend( '' )
+                       ->setSubmitTextMsg( 'withoutinterwiki-submit' )
+                       ->setMethod( 'get' )
+                       ->prepareForm()
+                       ->displayForm( false );
+       }
+
+       function sortDescending() {
+               return false;
+       }
+
+       function getOrderFields() {
+               return [ 'page_namespace', 'page_title' ];
+       }
+
+       function isExpensive() {
+               return true;
+       }
+
+       function isSyndicated() {
+               return false;
+       }
+
+       function getQueryInfo() {
+               $query = [
+                       'tables' => [ 'page', 'langlinks' ],
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_title'
+                       ],
+                       'conds' => [
+                               'll_title IS NULL',
+                               'page_namespace' => MediaWikiServices::getInstance()->getNamespaceInfo()->
+                                       getContentNamespaces(),
+                               'page_is_redirect' => 0
+                       ],
+                       'join_conds' => [ 'langlinks' => [ 'LEFT JOIN', 'll_from = page_id' ] ]
+               ];
+               if ( $this->prefix ) {
+                       $dbr = wfGetDB( DB_REPLICA );
+                       $query['conds'][] = 'page_title ' . $dbr->buildLike( $this->prefix, $dbr->anyString() );
+               }
+
+               return $query;
+       }
+
+       protected function getGroupName() {
+               return 'maintenance';
+       }
+}
diff --git a/includes/specials/SpecialWithoutinterwiki.php b/includes/specials/SpecialWithoutinterwiki.php
deleted file mode 100644 (file)
index 548e921..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-<?php
-/**
- * Implements Special:Withoutinterwiki
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- * http://www.gnu.org/copyleft/gpl.html
- *
- * @file
- * @ingroup SpecialPage
- * @author Rob Church <robchur@gmail.com>
- */
-
-use MediaWiki\MediaWikiServices;
-
-/**
- * Special page lists pages without language links
- *
- * @ingroup SpecialPage
- */
-class WithoutInterwikiPage extends PageQueryPage {
-       private $prefix = '';
-
-       function __construct( $name = 'Withoutinterwiki' ) {
-               parent::__construct( $name );
-       }
-
-       function execute( $par ) {
-               $this->prefix = Title::capitalize(
-                       $this->getRequest()->getVal( 'prefix', $par ), NS_MAIN );
-               parent::execute( $par );
-       }
-
-       function getPageHeader() {
-               # Do not show useless input form if special page is cached
-               if ( $this->isCached() ) {
-                       return '';
-               }
-
-               $formDescriptor = [
-                       'prefix' => [
-                               'label-message' => 'allpagesprefix',
-                               'name' => 'prefix',
-                               'id' => 'wiprefix',
-                               'type' => 'text',
-                               'size' => 20,
-                               'default' => $this->prefix
-                       ]
-               ];
-
-               $htmlForm = HTMLForm::factory( 'ooui', $formDescriptor, $this->getContext() );
-               $htmlForm->setWrapperLegend( '' )
-                       ->setSubmitTextMsg( 'withoutinterwiki-submit' )
-                       ->setMethod( 'get' )
-                       ->prepareForm()
-                       ->displayForm( false );
-       }
-
-       function sortDescending() {
-               return false;
-       }
-
-       function getOrderFields() {
-               return [ 'page_namespace', 'page_title' ];
-       }
-
-       function isExpensive() {
-               return true;
-       }
-
-       function isSyndicated() {
-               return false;
-       }
-
-       function getQueryInfo() {
-               $query = [
-                       'tables' => [ 'page', 'langlinks' ],
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_title'
-                       ],
-                       'conds' => [
-                               'll_title IS NULL',
-                               'page_namespace' => MediaWikiServices::getInstance()->getNamespaceInfo()->
-                                       getContentNamespaces(),
-                               'page_is_redirect' => 0
-                       ],
-                       'join_conds' => [ 'langlinks' => [ 'LEFT JOIN', 'll_from = page_id' ] ]
-               ];
-               if ( $this->prefix ) {
-                       $dbr = wfGetDB( DB_REPLICA );
-                       $query['conds'][] = 'page_title ' . $dbr->buildLike( $this->prefix, $dbr->anyString() );
-               }
-
-               return $query;
-       }
-
-       protected function getGroupName() {
-               return 'maintenance';
-       }
-}
index ea23973..b1bfd0b 100644 (file)
@@ -73,16 +73,18 @@ class PreferencesFormOOUI extends OOUIHTMLForm {
         * @return string
         */
        function getButtons() {
-               if ( !MediaWikiServices::getInstance()
-                       ->getPermissionManager()
-                       ->userHasAnyRight( $this->getModifiedUser(), 'editmyprivateinfo', 'editmyoptions' )
-               ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( !$permissionManager->userHasAnyRight(
+                       $this->getModifiedUser(),
+                       'editmyprivateinfo',
+                       'editmyoptions'
+               ) ) {
                        return '';
                }
 
                $html = parent::getButtons();
 
-               if ( $this->getModifiedUser()->isAllowed( 'editmyoptions' ) ) {
+               if ( $permissionManager->userHasRight( $this->getModifiedUser(), 'editmyoptions' ) ) {
                        $t = $this->getTitle()->getSubpage( 'reset' );
 
                        $html .= new OOUI\ButtonWidget( [
index 1e5f816..0b4e058 100644 (file)
@@ -76,7 +76,10 @@ class UploadForm extends HTMLForm {
                parent::__construct( $descriptor, $context, 'upload' );
 
                # Add a link to edit MediaWiki:Licenses
-               if ( $this->getUser()->isAllowed( 'editinterface' ) ) {
+               if ( MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'editinterface' )
+               ) {
                        $this->getOutput()->addModuleStyles( 'mediawiki.special' );
                        $licensesLink = $linkRenderer->makeKnownLink(
                                $this->msg( 'licenses' )->inContentLanguage()->getTitle(),
index 7703e20..c9c3b07 100644 (file)
@@ -19,6 +19,8 @@
  * @ingroup Pager
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This class is used to get a list of active users. The ones with specials
  * rights (sysop, bureaucrat, developer) will have them displayed
@@ -43,6 +45,12 @@ class ActiveUsersPager extends UsersPager {
         */
        private $blockStatusByUid;
 
+       /** @var int */
+       private $RCMaxAge;
+
+       /** @var string[] */
+       private $excludegroups;
+
        /**
         * @param IContextSource|null $context
         * @param FormOptions $opts
@@ -79,19 +87,16 @@ class ActiveUsersPager extends UsersPager {
        function getQueryInfo( $data = null ) {
                $dbr = $this->getDatabase();
 
-               $useActor = (bool)(
-                       $this->getConfig()->get( 'ActorTableSchemaMigrationStage' ) & SCHEMA_COMPAT_READ_NEW
-               );
-
                $activeUserSeconds = $this->getConfig()->get( 'ActiveUserDays' ) * 86400;
                $timestamp = $dbr->timestamp( wfTimestamp( TS_UNIX ) - $activeUserSeconds );
                $fname = __METHOD__ . ' (' . $this->getSqlComment() . ')';
 
                // Inner subselect to pull the active users out of querycachetwo
-               $tables = [ 'querycachetwo', 'user' ];
-               $fields = [ 'qcc_title', 'user_id' ];
+               $tables = [ 'querycachetwo', 'user', 'actor' ];
+               $fields = [ 'qcc_title', 'user_id', 'actor_id' ];
                $jconds = [
                        'user' => [ 'JOIN', 'user_name = qcc_title' ],
+                       'actor' => [ 'JOIN', 'actor_user = user_id' ],
                ];
                $conds = [
                        'qcc_type' => 'activeusers',
@@ -121,25 +126,20 @@ class ActiveUsersPager extends UsersPager {
                        ] ];
                        $conds['ug2.ug_user'] = null;
                }
-               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                                 ->getPermissionManager()
+                                 ->userHasRight( $this->getUser(), 'hideuser' )
+               ) {
                        $conds[] = 'NOT EXISTS (' . $dbr->selectSQLText(
                                        'ipblocks', '1', [ 'ipb_user=user_id', 'ipb_deleted' => 1 ]
                                ) . ')';
                }
-               if ( $useActor ) {
-                       $tables[] = 'actor';
-                       $jconds['actor'] = [
-                               'JOIN',
-                               'actor_user = user_id',
-                       ];
-                       $fields[] = 'actor_id';
-               }
                $subquery = $dbr->buildSelectSubquery( $tables, $fields, $conds, $fname, $options, $jconds );
 
                // Outer query to select the recent edit counts for the selected active users
                $tables = [ 'qcc_users' => $subquery, 'recentchanges' ];
                $jconds = [ 'recentchanges' => [ 'LEFT JOIN', [
-                       $useActor ? 'rc_actor = actor_id' : 'rc_user_text = qcc_title',
+                       'rc_actor = actor_id',
                        'rc_type != ' . $dbr->addQuotes( RC_EXTERNAL ), // Don't count wikidata.
                        'rc_type != ' . $dbr->addQuotes( RC_CATEGORIZE ), // Don't count categorization changes.
                        'rc_log_type IS NULL OR rc_log_type != ' . $dbr->addQuotes( 'newusers' ),
index c804b09..6b8b93b 100644 (file)
@@ -46,6 +46,11 @@ class AllMessagesTablePager extends TablePager {
         */
        protected $prefix;
 
+       /**
+        * @var string
+        */
+       protected $suffix;
+
        /**
         * @var Language
         */
index 4441a33..718da6d 100644 (file)
@@ -137,7 +137,10 @@ class BlockListPager extends TablePager {
                                        $value,
                                        /* User preference timezone */true
                                ) );
-                               if ( $this->getUser()->isAllowed( 'block' ) ) {
+                               if ( MediaWikiServices::getInstance()
+                                               ->getPermissionManager()
+                                               ->userHasRight( $this->getUser(), 'block' )
+                               ) {
                                        $links = [];
                                        if ( $row->ipb_auto ) {
                                                $links[] = $linkRenderer->makeKnownLink(
@@ -358,7 +361,10 @@ class BlockListPager extends TablePager {
                $info['conds'][] = 'ipb_expiry > ' . $db->addQuotes( $db->timestamp() );
 
                # Is the user allowed to see hidden blocks?
-               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'hideuser' )
+               ) {
                        $info['conds']['ipb_deleted'] = 0;
                }
 
index d76dfb8..3a56a87 100644 (file)
@@ -269,6 +269,7 @@ class ContribsPager extends RangeChronologicalPager {
                        'options' => [],
                        'join_conds' => $revQuery['joins'],
                ];
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
 
                // WARNING: Keep this in sync with getTargetTable()!
                $user = User::newFromName( $this->target, false );
@@ -313,14 +314,11 @@ class ContribsPager extends RangeChronologicalPager {
                $queryInfo['conds'] = array_merge( $queryInfo['conds'], $this->getNamespaceCond() );
 
                // Paranoia: avoid brute force searches (T19342)
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+               if ( !$permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
                        $queryInfo['conds'][] = $this->mDb->bitAnd(
                                'rev_deleted', RevisionRecord::DELETED_USER
                                ) . ' = 0';
-               } elseif ( !MediaWikiServices::getInstance()
-                       ->getPermissionManager()
-                       ->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' )
-               ) {
+               } elseif ( !$permissionManager->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' ) ) {
                        $queryInfo['conds'][] = $this->mDb->bitAnd(
                                'rev_deleted', RevisionRecord::SUPPRESSED_USER
                                ) . ' != ' . RevisionRecord::SUPPRESSED_USER;
index cd6294d..2893759 100644 (file)
@@ -90,13 +90,11 @@ class DeletedContribsPager extends IndexPager {
                ];
                $conds = array_merge( $userCond, $this->getNamespaceCond() );
                $user = $this->getUser();
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
                // Paranoia: avoid brute force searches (T19792)
-               if ( !$user->isAllowed( 'deletedhistory' ) ) {
+               if ( !$permissionManager->userHasRight( $user, 'deletedhistory' ) ) {
                        $conds[] = $this->mDb->bitAnd( 'ar_deleted', RevisionRecord::DELETED_USER ) . ' = 0';
-               } elseif ( !MediaWikiServices::getInstance()
-                       ->getPermissionManager()
-                       ->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' )
-               ) {
+               } elseif ( !$permissionManager->userHasAnyRight( $user, 'suppressrevision', 'viewsuppressed' ) ) {
                        $conds[] = $this->mDb->bitAnd( 'ar_deleted', RevisionRecord::SUPPRESSED_USER ) .
                                ' != ' . RevisionRecord::SUPPRESSED_USER;
                }
@@ -325,8 +323,9 @@ class DeletedContribsPager extends IndexPager {
                );
 
                $user = $this->getUser();
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
 
-               if ( $user->isAllowed( 'deletedtext' ) ) {
+               if ( $permissionManager->userHasRight( $user, 'deletedtext' ) ) {
                        $last = $linkRenderer->makeKnownLink(
                                $undelete,
                                $this->messages['diff'],
@@ -344,7 +343,9 @@ class DeletedContribsPager extends IndexPager {
                $comment = Linker::revComment( $rev );
                $date = $this->getLanguage()->userTimeAndDate( $rev->getTimestamp(), $user );
 
-               if ( !$user->isAllowed( 'undelete' ) || !$rev->userCan( RevisionRecord::DELETED_TEXT, $user ) ) {
+               if ( !$permissionManager->userHasRight( $user, 'undelete' ) ||
+                        !$rev->userCan( RevisionRecord::DELETED_TEXT, $user )
+               ) {
                        $link = htmlspecialchars( $date ); // unusable link
                } else {
                        $link = $linkRenderer->makeKnownLink(
index 9415cea..81c3ffb 100644 (file)
@@ -30,10 +30,15 @@ class MergeHistoryPager extends ReverseChronologicalPager {
        /** @var array */
        public $mConds;
 
+       /** @var int */
+       private $articleID;
+
+       /** @var int */
+       private $maxTimestamp;
+
        public function __construct( SpecialMergeHistory $form, $conds, Title $source, Title $dest ) {
                $this->mForm = $form;
                $this->mConds = $conds;
-               $this->title = $source;
                $this->articleID = $source->getArticleID();
 
                $dbr = wfGetDB( DB_REPLICA );
index f1b0b9a..be4a1bd 100644 (file)
@@ -97,27 +97,17 @@ class NewFilesPager extends RangeChronologicalPager {
                }
 
                if ( $opts->getValue( 'hidepatrolled' ) ) {
-                       global $wgActorTableSchemaMigrationStage;
-
                        $tables[] = 'recentchanges';
                        $conds['rc_type'] = RC_LOG;
                        $conds['rc_log_type'] = 'upload';
                        $conds['rc_patrolled'] = RecentChange::PRC_UNPATROLLED;
                        $conds['rc_namespace'] = NS_FILE;
 
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) {
-                               $jcond = 'rc_actor = ' . $imgQuery['fields']['img_actor'];
-                       } else {
-                               $rcQuery = ActorMigration::newMigration()->getJoin( 'rc_user' );
-                               $tables += $rcQuery['tables'];
-                               $jconds += $rcQuery['joins'];
-                               $jcond = $rcQuery['fields']['rc_user'] . ' = ' . $imgQuery['fields']['img_user'];
-                       }
                        $jconds['recentchanges'] = [
                                'JOIN',
                                [
                                        'rc_title = img_name',
-                                       $jcond,
+                                       'rc_actor = ' . $imgQuery['fields']['img_actor'],
                                        'rc_timestamp = img_timestamp'
                                ]
                        ];
index 747dea2..bb5592c 100644 (file)
@@ -20,6 +20,7 @@
  */
 
 use MediaWiki\Linker\LinkRenderer;
+use MediaWiki\MediaWikiServices;
 
 class ProtectedPagesPager extends TablePager {
 
@@ -159,7 +160,10 @@ class ProtectedPagesPager extends TablePager {
                                $formatted = htmlspecialchars( $this->getLanguage()->formatExpiry(
                                        $value, /* User preference timezone */true ) );
                                $title = Title::makeTitleSafe( $row->page_namespace, $row->page_title );
-                               if ( $this->getUser()->isAllowed( 'protect' ) && $title ) {
+                               if ( $title && MediaWikiServices::getInstance()
+                                                ->getPermissionManager()
+                                                ->userHasRight( $this->getUser(), 'protect' )
+                               ) {
                                        $changeProtection = $linkRenderer->makeKnownLink(
                                                $title,
                                                $this->msg( 'protect_change' )->text(),
index 296fe11..a00b371 100644 (file)
@@ -34,6 +34,12 @@ class ProtectedTitlesPager extends AlphabeticPager {
         */
        public $mConds;
 
+       /** @var string|null */
+       private $level;
+
+       /** @var int|null */
+       private $namespace;
+
        /**
         * @param SpecialProtectedtitles $form
         * @param array $conds
@@ -50,7 +56,6 @@ class ProtectedTitlesPager extends AlphabeticPager {
                $this->mConds = $conds;
                $this->level = $level;
                $this->namespace = $namespace;
-               $this->size = intval( $size );
                parent::__construct( $form->getContext() );
        }
 
@@ -90,7 +95,7 @@ class ProtectedTitlesPager extends AlphabeticPager {
                        $conds['pt_create_perm'] = $this->level;
                }
 
-               if ( !is_null( $this->namespace ) ) {
+               if ( $this->namespace !== null ) {
                        $conds[] = 'pt_namespace=' . $this->mDb->addQuotes( $this->namespace );
                }
 
index 57b575b..ee0ac00 100644 (file)
@@ -23,6 +23,8 @@
  * @ingroup Pager
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * This class is used to get a list of user. The ones with specials
  * rights (sysop, bureaucrat, developer) will have them displayed
@@ -37,6 +39,24 @@ class UsersPager extends AlphabeticPager {
         */
        protected $userGroupCache;
 
+       /** @var string */
+       protected $requestedGroup;
+
+       /** @var bool */
+       protected $editsOnly;
+
+       /** @var bool */
+       protected $temporaryGroupsOnly;
+
+       /** @var bool */
+       protected $creationSort;
+
+       /** @var bool|null */
+       protected $including;
+
+       /** @var string */
+       protected $requestedUser;
+
        /**
         * @param IContextSource|null $context
         * @param array|null $par (Default null)
@@ -105,7 +125,10 @@ class UsersPager extends AlphabeticPager {
                $conds = [];
 
                // Don't show hidden names
-               if ( !$this->getUser()->isAllowed( 'hideuser' ) ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $this->getUser(), 'hideuser' )
+               ) {
                        $conds[] = 'ipb_deleted IS NULL OR ipb_deleted = 0';
                }
 
index 3368e29..d7dfffa 100644 (file)
  * @file
  * @ingroup Upload
  */
+
+use MediaWiki\MediaWikiServices;
 use MediaWiki\Shell\Shell;
+use MediaWiki\User\UserIdentity;
 
 /**
  * @defgroup Upload Upload related
@@ -145,12 +148,13 @@ abstract class UploadBase {
         * identifying the missing permission.
         * Can be overridden by subclasses.
         *
-        * @param User $user
+        * @param UserIdentity $user
         * @return bool|string
         */
-       public static function isAllowed( $user ) {
+       public static function isAllowed( UserIdentity $user ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
                foreach ( [ 'upload', 'edit' ] as $permission ) {
-                       if ( !$user->isAllowed( $permission ) ) {
+                       if ( !$permissionManager->userHasRight( $user, $permission ) ) {
                                return $permission;
                        }
                }
@@ -1954,7 +1958,10 @@ abstract class UploadBase {
                 * wfFindFile finds a file, it exists in a shared repository.
                 */
                $file = wfFindFile( $this->getTitle(), [ 'latest' => true ] );
-               if ( $file && !$user->isAllowed( 'reupload-shared' ) ) {
+               if ( $file && !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'reupload-shared' )
+               ) {
                        return [ 'fileexists-shared-forbidden', $file->getName() ];
                }
 
@@ -1969,9 +1976,10 @@ abstract class UploadBase {
         * @return bool
         */
        public static function userCanReUpload( User $user, File $img ) {
-               if ( $user->isAllowed( 'reupload' ) ) {
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
+               if ( $permissionManager->userHasRight( $user, 'reupload' ) ) {
                        return true; // non-conditional
-               } elseif ( !$user->isAllowed( 'reupload-own' ) ) {
+               } elseif ( !$permissionManager->userHasRight( $user, 'reupload-own' ) ) {
                        return false;
                }
 
index b92fcc5..b87810d 100644 (file)
@@ -1,7 +1,4 @@
 <?php
-
-use MediaWiki\MediaWikiServices;
-
 /**
  * Backend for uploading files from a HTTP resource.
  *
@@ -24,6 +21,9 @@ use MediaWiki\MediaWikiServices;
  * @ingroup Upload
  */
 
+use MediaWiki\MediaWikiServices;
+use MediaWiki\User\UserIdentity;
+
 /**
  * Implements uploading from a HTTP resource.
  *
@@ -43,12 +43,15 @@ class UploadFromUrl extends UploadBase {
         * user is not allowed, return the name of the user right as a string. If
         * the user is allowed, have the parent do further permissions checking.
         *
-        * @param User $user
+        * @param UserIdentity $user
         *
         * @return bool|string
         */
-       public static function isAllowed( $user ) {
-               if ( !$user->isAllowed( 'upload_by_url' ) ) {
+       public static function isAllowed( UserIdentity $user ) {
+               if ( !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $user, 'upload_by_url' )
+               ) {
                        return 'upload_by_url';
                }
 
@@ -167,7 +170,9 @@ class UploadFromUrl extends UploadBase {
                $url = $request->getVal( 'wpUploadFileURL' );
 
                return !empty( $url )
-                       && $wgUser->isAllowed( 'upload_by_url' );
+                       && MediaWikiServices::getInstance()
+                                  ->getPermissionManager()
+                                  ->userHasRight( $wgUser, 'upload_by_url' );
        }
 
        /**
index ca3db5b..4c9099e 100644 (file)
@@ -20,6 +20,8 @@
  * @file
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * A CentralIdLookup provider that just uses local IDs. Useful if the wiki
  * isn't part of a cluster or you're using shared user tables.
@@ -69,7 +71,10 @@ class LocalIdLookup extends CentralIdLookup {
                        'user_id' => array_map( 'intval', array_keys( $idToName ) ),
                ];
                $join = [];
-               if ( $audience && !$audience->isAllowed( 'hideuser' ) ) {
+               if ( $audience && !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $audience, 'hideuser' )
+               ) {
                        $tables[] = 'ipblocks';
                        $join['ipblocks'] = [ 'LEFT JOIN', 'ipb_user=user_id' ];
                        $fields[] = 'ipb_deleted';
@@ -100,7 +105,10 @@ class LocalIdLookup extends CentralIdLookup {
                        'user_name' => array_map( 'strval', array_keys( $nameToId ) ),
                ];
                $join = [];
-               if ( $audience && !$audience->isAllowed( 'hideuser' ) ) {
+               if ( $audience && !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $audience, 'hideuser' )
+               ) {
                        $tables[] = 'ipblocks';
                        $join['ipblocks'] = [ 'LEFT JOIN', 'ipb_user=user_id' ];
                        $where[] = 'ipb_deleted = 0 OR ipb_deleted IS NULL';
index fd8eb3f..38707de 100644 (file)
@@ -22,6 +22,7 @@
 
 use MediaWiki\Auth\AuthManager;
 use MediaWiki\Auth\TemporaryPasswordAuthenticationRequest;
+use MediaWiki\Permissions\PermissionManager;
 use Psr\Log\LoggerAwareInterface;
 use Psr\Log\LoggerInterface;
 use MediaWiki\Logger\LoggerFactory;
@@ -40,6 +41,9 @@ class PasswordReset implements LoggerAwareInterface {
        /** @var AuthManager */
        protected $authManager;
 
+       /** @var PermissionManager */
+       private $permissionManager;
+
        /** @var LoggerInterface */
        protected $logger;
 
@@ -50,9 +54,14 @@ class PasswordReset implements LoggerAwareInterface {
         */
        private $permissionCache;
 
-       public function __construct( Config $config, AuthManager $authManager ) {
+       public function __construct(
+               Config $config,
+               AuthManager $authManager,
+               PermissionManager $permissionManager
+       ) {
                $this->config = $config;
                $this->authManager = $authManager;
+               $this->permissionManager = $permissionManager;
                $this->permissionCache = new MapCacheLRU( 1 );
                $this->logger = LoggerFactory::getInstance( 'authentication' );
        }
@@ -93,7 +102,7 @@ class PasswordReset implements LoggerAwareInterface {
                        } elseif ( !$this->config->get( 'EnableEmail' ) ) {
                                // Maybe email features have been disabled
                                $status = StatusValue::newFatal( 'passwordreset-emaildisabled' );
-                       } elseif ( !$user->isAllowed( 'editmyprivateinfo' ) ) {
+                       } elseif ( !$this->permissionManager->userHasRight( $user, 'editmyprivateinfo' ) ) {
                                // Maybe not all users have permission to change private data
                                $status = StatusValue::newFatal( 'badaccess' );
                        } elseif ( $this->isBlocked( $user ) ) {
index 7068879..fc96fe1 100644 (file)
@@ -64,7 +64,7 @@ class User implements IDBAccessObject, UserIdentity {
         * Version number to tag cached versions of serialized User objects. Should be increased when
         * {@link $mCacheVars} or one of it's members changes.
         */
-       const VERSION = 13;
+       const VERSION = 14;
 
        /**
         * Exclude user options that are set to their default value.
@@ -327,22 +327,6 @@ class User implements IDBAccessObject, UserIdentity {
                        case 'defaults':
                                $this->loadDefaults();
                                break;
-                       case 'name':
-                               // Make sure this thread sees its own changes
-                               $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
-                               if ( $lb->hasOrMadeRecentMasterChanges() ) {
-                                       $flags |= self::READ_LATEST;
-                                       $this->queryFlagsUsed = $flags;
-                               }
-
-                               $this->mId = self::idFromName( $this->mName, $flags );
-                               if ( !$this->mId ) {
-                                       // Nonexistent user placeholder object
-                                       $this->loadDefaults( $this->mName );
-                               } else {
-                                       $this->loadFromId( $flags );
-                               }
-                               break;
                        case 'id':
                                // Make sure this thread sees its own changes, if the ID isn't 0
                                if ( $this->mId != 0 ) {
@@ -356,6 +340,7 @@ class User implements IDBAccessObject, UserIdentity {
                                $this->loadFromId( $flags );
                                break;
                        case 'actor':
+                       case 'name':
                                // Make sure this thread sees its own changes
                                $lb = MediaWikiServices::getInstance()->getDBLoadBalancer();
                                if ( $lb->hasOrMadeRecentMasterChanges() ) {
@@ -366,20 +351,20 @@ class User implements IDBAccessObject, UserIdentity {
                                list( $index, $options ) = DBAccessObjectUtils::getDBOptions( $flags );
                                $row = wfGetDB( $index )->selectRow(
                                        'actor',
-                                       [ 'actor_user', 'actor_name' ],
-                                       [ 'actor_id' => $this->mActorId ],
+                                       [ 'actor_id', 'actor_user', 'actor_name' ],
+                                       $this->mFrom === 'name' ? [ 'actor_name' => $this->mName ] : [ 'actor_id' => $this->mActorId ],
                                        __METHOD__,
                                        $options
                                );
 
                                if ( !$row ) {
                                        // Ugh.
-                                       $this->loadDefaults();
+                                       $this->loadDefaults( $this->mFrom === 'name' ? $this->mName : false );
                                } elseif ( $row->actor_user ) {
                                        $this->mId = $row->actor_user;
                                        $this->loadFromId( $flags );
                                } else {
-                                       $this->loadDefaults( $row->actor_name );
+                                       $this->loadDefaults( $row->actor_name, $row->actor_id );
                                }
                                break;
                        case 'session':
@@ -567,17 +552,6 @@ class User implements IDBAccessObject, UserIdentity {
         * @return User The corresponding User object
         */
        public static function newFromActorId( $id ) {
-               global $wgActorTableSchemaMigrationStage;
-
-               // Technically we shouldn't allow this without SCHEMA_COMPAT_READ_NEW,
-               // but it does little harm and might be needed for write callers loading a User.
-               if ( !( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_NEW ) ) {
-                       throw new BadMethodCallException(
-                               'Cannot use ' . __METHOD__
-                                       . ' when $wgActorTableSchemaMigrationStage lacks SCHEMA_COMPAT_NEW'
-                       );
-               }
-
                $u = new User;
                $u->mActorId = $id;
                $u->mFrom = 'actor';
@@ -620,8 +594,6 @@ class User implements IDBAccessObject, UserIdentity {
         * @return User
         */
        public static function newFromAnyId( $userId, $userName, $actorId, $dbDomain = false ) {
-               global $wgActorTableSchemaMigrationStage;
-
                // Stop-gap solution for the problem described in T222212.
                // Force the User ID and Actor ID to zero for users loaded from the database
                // of another wiki, to prevent subtle data corruption and confusing failure modes.
@@ -633,9 +605,7 @@ class User implements IDBAccessObject, UserIdentity {
                $user = new User;
                $user->mFrom = 'defaults';
 
-               // Technically we shouldn't allow this without SCHEMA_COMPAT_READ_NEW,
-               // but it does little harm and might be needed for write callers loading a User.
-               if ( ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_NEW ) && $actorId !== null ) {
+               if ( $actorId !== null ) {
                        $user->mActorId = (int)$actorId;
                        if ( $user->mActorId !== 0 ) {
                                $user->mFrom = 'actor';
@@ -1220,11 +1190,12 @@ class User implements IDBAccessObject, UserIdentity {
         *       the constructor does that instead.
         *
         * @param string|bool $name
+        * @param int|null $actorId
         */
-       public function loadDefaults( $name = false ) {
+       public function loadDefaults( $name = false, $actorId = null ) {
                $this->mId = 0;
                $this->mName = $name;
-               $this->mActorId = null;
+               $this->mActorId = $actorId;
                $this->mRealName = '';
                $this->mEmail = '';
                $this->mOptionOverrides = null;
@@ -1375,8 +1346,6 @@ class User implements IDBAccessObject, UserIdentity {
         *  user_properties   Array with properties out of the user_properties table
         */
        protected function loadFromRow( $row, $data = null ) {
-               global $wgActorTableSchemaMigrationStage;
-
                if ( !is_object( $row ) ) {
                        throw new InvalidArgumentException( '$row must be an object' );
                }
@@ -1385,18 +1354,14 @@ class User implements IDBAccessObject, UserIdentity {
 
                $this->mGroupMemberships = null; // deferred
 
-               // Technically we shouldn't allow this without SCHEMA_COMPAT_READ_NEW,
-               // but it does little harm and might be needed for write callers loading a User.
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_NEW ) {
-                       if ( isset( $row->actor_id ) ) {
-                               $this->mActorId = (int)$row->actor_id;
-                               if ( $this->mActorId !== 0 ) {
-                                       $this->mFrom = 'actor';
-                               }
-                               $this->setItemLoaded( 'actor' );
-                       } else {
-                               $all = false;
+               if ( isset( $row->actor_id ) ) {
+                       $this->mActorId = (int)$row->actor_id;
+                       if ( $this->mActorId !== 0 ) {
+                               $this->mFrom = 'actor';
                        }
+                       $this->setItemLoaded( 'actor' );
+               } else {
+                       $all = false;
                }
 
                if ( isset( $row->user_name ) && $row->user_name !== '' ) {
@@ -1753,9 +1718,31 @@ class User implements IDBAccessObject, UserIdentity {
                // overwriting mBlockedby, surely?
                $this->load();
 
+               // TODO: Block checking shouldn't really be done from the User object. Block
+               // checking can involve checking for IP blocks, cookie blocks, and/or XFF blocks,
+               // which need more knowledge of the request context than the User should have.
+               // Since we do currently check blocks from the User, we have to do the following
+               // here:
+               // - Check if this is the user associated with the main request
+               // - If so, pass the relevant request information to the block manager
+               $request = null;
+
+               // The session user is set up towards the end of Setup.php. Until then,
+               // assume it's a logged-out user.
+               $sessionUser = RequestContext::getMain()->getUser();
+               $globalUserName = $sessionUser->isSafeToLoad()
+                       ? $sessionUser->getName()
+                       : IP::sanitizeIP( $sessionUser->getRequest()->getIP() );
+
+               if ( $this->getName() === $globalUserName ) {
+                       // This is the global user, so we need to pass the request
+                       $request = $this->getRequest();
+               }
+
                // @phan-suppress-next-line PhanAccessMethodInternal It's the only allowed use
                $block = MediaWikiServices::getInstance()->getBlockManager()->getUserBlock(
                        $this,
+                       $request,
                        $fromReplica
                );
 
@@ -1776,7 +1763,7 @@ class User implements IDBAccessObject, UserIdentity {
                // Avoid PHP 7.1 warning of passing $this by reference
                $thisUser = $this;
                // Extensions
-               Hooks::run( 'GetBlockedStatus', [ &$thisUser ] );
+               Hooks::run( 'GetBlockedStatus', [ &$thisUser ], '1.34' );
        }
 
        /**
@@ -2204,7 +2191,7 @@ class User implements IDBAccessObject, UserIdentity {
                if ( !$this->mHideName ) {
                        // Reset for hook
                        $this->mHideName = false;
-                       Hooks::run( 'UserIsHidden', [ $this, &$this->mHideName ] );
+                       Hooks::run( 'UserIsHidden', [ $this, &$this->mHideName ], '1.34' );
                }
                return (bool)$this->mHideName;
        }
@@ -2214,7 +2201,9 @@ class User implements IDBAccessObject, UserIdentity {
         * @return int The user's ID; 0 if the user is anonymous or nonexistent
         */
        public function getId() {
-               if ( $this->mId === null && $this->mName !== null && self::isIP( $this->mName ) ) {
+               if ( $this->mId === null && $this->mName !== null &&
+                       ( self::isIP( $this->mName ) || ExternalUserNames::isExternal( $this->mName ) )
+               ) {
                        // Special case, we know the user is anonymous
                        return 0;
                }
@@ -2280,62 +2269,43 @@ class User implements IDBAccessObject, UserIdentity {
         * @return int The actor's ID, or 0 if no actor ID exists and $dbw was null
         */
        public function getActorId( IDatabase $dbw = null ) {
-               global $wgActorTableSchemaMigrationStage;
-
-               // Technically we should always return 0 without SCHEMA_COMPAT_READ_NEW,
-               // but it does little harm and might be needed for write callers loading a User.
-               if ( !( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) ) {
-                       return 0;
-               }
-
                if ( !$this->isItemLoaded( 'actor' ) ) {
                        $this->load();
                }
 
-               // Currently $this->mActorId might be null if $this was loaded from a
-               // cache entry that was written when $wgActorTableSchemaMigrationStage
-               // was SCHEMA_COMPAT_OLD. Once that is no longer a possibility (i.e. when
-               // User::VERSION is incremented after $wgActorTableSchemaMigrationStage
-               // has been removed), that condition may be removed.
-               if ( $this->mActorId === null || !$this->mActorId && $dbw ) {
+               if ( !$this->mActorId && $dbw ) {
                        $q = [
                                'actor_user' => $this->getId() ?: null,
                                'actor_name' => (string)$this->getName(),
                        ];
-                       if ( $dbw ) {
-                               if ( $q['actor_user'] === null && self::isUsableName( $q['actor_name'] ) ) {
+                       if ( $q['actor_user'] === null && self::isUsableName( $q['actor_name'] ) ) {
+                               throw new CannotCreateActorException(
+                                       'Cannot create an actor for a usable name that is not an existing user'
+                               );
+                       }
+                       if ( $q['actor_name'] === '' ) {
+                               throw new CannotCreateActorException( 'Cannot create an actor for a user with no name' );
+                       }
+                       $dbw->insert( 'actor', $q, __METHOD__, [ 'IGNORE' ] );
+                       if ( $dbw->affectedRows() ) {
+                               $this->mActorId = (int)$dbw->insertId();
+                       } else {
+                               // Outdated cache?
+                               // Use LOCK IN SHARE MODE to bypass any MySQL REPEATABLE-READ snapshot.
+                               $this->mActorId = (int)$dbw->selectField(
+                                       'actor',
+                                       'actor_id',
+                                       $q,
+                                       __METHOD__,
+                                       [ 'LOCK IN SHARE MODE' ]
+                               );
+                               if ( !$this->mActorId ) {
                                        throw new CannotCreateActorException(
-                                               'Cannot create an actor for a usable name that is not an existing user'
+                                               "Cannot create actor ID for user_id={$this->getId()} user_name={$this->getName()}"
                                        );
                                }
-                               if ( $q['actor_name'] === '' ) {
-                                       throw new CannotCreateActorException( 'Cannot create an actor for a user with no name' );
-                               }
-                               $dbw->insert( 'actor', $q, __METHOD__, [ 'IGNORE' ] );
-                               if ( $dbw->affectedRows() ) {
-                                       $this->mActorId = (int)$dbw->insertId();
-                               } else {
-                                       // Outdated cache?
-                                       // Use LOCK IN SHARE MODE to bypass any MySQL REPEATABLE-READ snapshot.
-                                       $this->mActorId = (int)$dbw->selectField(
-                                               'actor',
-                                               'actor_id',
-                                               $q,
-                                               __METHOD__,
-                                               [ 'LOCK IN SHARE MODE' ]
-                                       );
-                                       if ( !$this->mActorId ) {
-                                               throw new CannotCreateActorException(
-                                                       "Cannot create actor ID for user_id={$this->getId()} user_name={$this->getName()}"
-                                               );
-                                       }
-                               }
-                               $this->invalidateCache();
-                       } else {
-                               list( $index, $options ) = DBAccessObjectUtils::getDBOptions( $this->queryFlagsUsed );
-                               $db = wfGetDB( $index );
-                               $this->mActorId = (int)$db->selectField( 'actor', 'actor_id', $q, __METHOD__, $options );
                        }
+                       $this->invalidateCache();
                        $this->setItemLoaded( 'actor' );
                }
 
@@ -2824,18 +2794,6 @@ class User implements IDBAccessObject, UserIdentity {
                }
        }
 
-       /**
-        * Set the password for a password reminder or new account email
-        *
-        * @deprecated Removed in 1.27. Use PasswordReset instead.
-        * @param string $str New password to set or null to set an invalid
-        *  password hash meaning that the user will not be able to use it
-        * @param bool $throttle If true, reset the throttle timestamp to the present
-        */
-       public function setNewpassword( $str, $throttle = true ) {
-               throw new BadMethodCallException( __METHOD__ . ' has been removed in 1.27' );
-       }
-
        /**
         * Get the user's e-mail address
         * @return string User's email address
@@ -3768,11 +3726,17 @@ class User implements IDBAccessObject, UserIdentity {
                                $this->setNewtalk( false );
 
                                // If there is a new, unseen, revision, use its timestamp
-                               $nextid = $oldid
-                                       ? $title->getNextRevisionID( $oldid, Title::GAID_FOR_UPDATE )
-                                       : null;
-                               if ( $nextid ) {
-                                       $this->setNewtalk( true, Revision::newFromId( $nextid ) );
+                               if ( $oldid ) {
+                                       $rl = MediaWikiServices::getInstance()->getRevisionLookup();
+                                       $oldRev = $rl->getRevisionById( $oldid, Title::READ_LATEST );
+                                       if ( $oldRev ) {
+                                               $newRev = $rl->getNextRevision( $oldRev );
+                                               if ( $newRev ) {
+                                                       // TODO: actually no need to wrap in a revision,
+                                                       // setNewtalk really only needs a RevRecord
+                                                       $this->setNewtalk( true, new Revision( $newRev ) );
+                                               }
+                                       }
                                }
                        } );
                }
@@ -3979,8 +3943,6 @@ class User implements IDBAccessObject, UserIdentity {
 
                $dbw = wfGetDB( DB_MASTER );
                $dbw->doAtomicSection( __METHOD__, function ( IDatabase $dbw, $fname ) use ( $newTouched ) {
-                       global $wgActorTableSchemaMigrationStage;
-
                        $dbw->update( 'user',
                                [ /* SET */
                                        'user_name' => $this->mName,
@@ -4010,14 +3972,12 @@ class User implements IDBAccessObject, UserIdentity {
                                );
                        }
 
-                       if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                               $dbw->update(
-                                       'actor',
-                                       [ 'actor_name' => $this->mName ],
-                                       [ 'actor_user' => $this->mId ],
-                                       $fname
-                               );
-                       }
+                       $dbw->update(
+                               'actor',
+                               [ 'actor_name' => $this->mName ],
+                               [ 'actor_user' => $this->mId ],
+                               $fname
+                       );
                } );
 
                $this->mTouched = $newTouched;
@@ -4216,16 +4176,12 @@ class User implements IDBAccessObject, UserIdentity {
         * @param IDatabase $dbw Writable database handle
         */
        private function updateActorId( IDatabase $dbw ) {
-               global $wgActorTableSchemaMigrationStage;
-
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                       $dbw->insert(
-                               'actor',
-                               [ 'actor_user' => $this->mId, 'actor_name' => $this->mName ],
-                               __METHOD__
-                       );
-                       $this->mActorId = (int)$dbw->insertId();
-               }
+               $dbw->insert(
+                       'actor',
+                       [ 'actor_user' => $this->mId, 'actor_name' => $this->mName ],
+                       __METHOD__
+               );
+               $this->mActorId = (int)$dbw->insertId();
        }
 
        /**
@@ -4358,13 +4314,13 @@ class User implements IDBAccessObject, UserIdentity {
                                'password' => $password,
                        ]
                );
-               $res = AuthManager::singleton()->beginAuthentication( $reqs, 'null:' );
+               $res = $manager->beginAuthentication( $reqs, 'null:' );
                switch ( $res->status ) {
                        case AuthenticationResponse::PASS:
                                return true;
                        case AuthenticationResponse::FAIL:
                                // Hope it's not a PreAuthenticationProvider that failed...
-                               \MediaWiki\Logger\LoggerFactory::getInstance( 'authentication' )
+                               LoggerFactory::getInstance( 'authentication' )
                                        ->info( __METHOD__ . ': Authentication failed: ' . $res->message->plain() );
                                return false;
                        default:
@@ -5296,10 +5252,8 @@ class User implements IDBAccessObject, UserIdentity {
         *   - joins: (array) to include in the `$join_conds` to `IDatabase->select()`
         */
        public static function getQueryInfo() {
-               global $wgActorTableSchemaMigrationStage;
-
                $ret = [
-                       'tables' => [ 'user' ],
+                       'tables' => [ 'user', 'user_actor' => 'actor' ],
                        'fields' => [
                                'user_id',
                                'user_name',
@@ -5312,21 +5266,13 @@ class User implements IDBAccessObject, UserIdentity {
                                'user_email_token_expires',
                                'user_registration',
                                'user_editcount',
+                               'user_actor.actor_id',
+                       ],
+                       'joins' => [
+                               'user_actor' => [ 'JOIN', 'user_actor.actor_user = user_id' ],
                        ],
-                       'joins' => [],
                ];
 
-               // Technically we shouldn't allow this without SCHEMA_COMPAT_READ_NEW,
-               // but it does little harm and might be needed for write callers loading a User.
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_NEW ) {
-                       $ret['tables']['user_actor'] = 'actor';
-                       $ret['fields'][] = 'user_actor.actor_id';
-                       $ret['joins']['user_actor'] = [
-                               ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_READ_NEW ) ? 'JOIN' : 'LEFT JOIN',
-                               [ 'user_actor.actor_user = user_id' ]
-                       ];
-               }
-
                return $ret;
        }
 
index c185bab..b3489a2 100644 (file)
@@ -20,6 +20,8 @@
  * @file
  */
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * Handles searching prefixes of user names
  *
@@ -46,7 +48,10 @@ class UserNamePrefixSearch {
                $joinConds = [];
 
                // Filter out hidden user names
-               if ( $audience === 'public' || !$audience->isAllowed( 'hideuser' ) ) {
+               if ( $audience === 'public' || !MediaWikiServices::getInstance()
+                               ->getPermissionManager()
+                               ->userHasRight( $audience, 'hideuser' )
+               ) {
                        $tables[] = 'ipblocks';
                        $cond['ipb_deleted'] = [ 0, null ];
                        $joinConds['ipblocks'] = [ 'LEFT JOIN', 'user_id=ipb_user' ];
index 06d8095..3ae00ea 100644 (file)
@@ -9,14 +9,22 @@ namespace MediaWiki\Widget;
  * @license MIT
  */
 class CheckMatrixWidget extends \OOUI\Widget {
-
-       protected $name = '';
-       protected $columns = [];
-       protected $rows = [];
-       protected $tooltips = [];
-       protected $values = [];
-       protected $forcedOn = [];
-       protected $forcedOff = [];
+       /** @var string|null */
+       protected $name;
+       /** @var string|null */
+       protected $id;
+       /** @var array */
+       protected $columns;
+       /** @var array */
+       protected $rows;
+       /** @var array */
+       protected $tooltips;
+       /** @var array */
+       protected $values;
+       /** @var array */
+       protected $forcedOn;
+       /** @var array */
+       protected $forcedOff;
 
        /**
         * Operates similarly to MultiSelectWidget, but instead of using an array of
index 7737067..913816c 100644 (file)
@@ -9,7 +9,8 @@ namespace MediaWiki\Widget;
  * @license MIT
  */
 class ComplexTitleInputWidget extends \OOUI\Widget {
-
+       /** @var array */
+       protected $config;
        protected $namespace = null;
        protected $title = null;
 
index 7802a2a..a360fb8 100644 (file)
@@ -9,8 +9,10 @@ namespace MediaWiki\Widget;
  * @license MIT
  */
 class NamespaceInputWidget extends \OOUI\DropdownInputWidget {
-
-       protected $includeAllValue = null;
+       /** @var string */
+       protected $includeAllValue;
+       /** @var int[] */
+       protected $exclude;
 
        /**
         * @param array $config Configuration options
index a946653..a792172 100644 (file)
@@ -12,9 +12,12 @@ use OOUI\TextInputWidget;
  * @license MIT
  */
 class SelectWithInputWidget extends \OOUI\Widget {
-
-       protected $textinput = null;
-       protected $dropdowninput = null;
+       /** @var array */
+       protected $config;
+       /** @var TextInputWidget */
+       protected $textinput;
+       /** @var DropdownInputWidget */
+       protected $dropdowninput;
 
        /**
         * A version of the SelectWithInputWidget, with `or` set to true.
index 18c05bf..26935b1 100644 (file)
@@ -13,9 +13,14 @@ use \OOUI\LabelWidget;
  * @license MIT
  */
 class SizeFilterWidget extends \OOUI\Widget {
-
-       protected $radioselectinput = null;
-       protected $textinput = null;
+       /** @var array */
+       protected $config;
+       /** @var LabelWidget */
+       protected $label;
+       /** @var RadioSelectInputWidget */
+       protected $radioselectinput;
+       /** @var TextInputWidget */
+       protected $textinput;
 
        /**
         * RadioSelectInputWidget and a TextInputWidget to set minimum or maximum byte size
index 43e184c..e96160c 100644 (file)
@@ -12,41 +12,34 @@ use OOUI\MultilineTextInputWidget;
  * @license MIT
  */
 abstract class TagMultiselectWidget extends \OOUI\Widget {
-
-       protected $selectedArray = [];
-       protected $inputName = null;
-       protected $inputPlaceholder = null;
-       protected $tagLimit = null;
+       /** @var array */
+       protected $selectedArray;
+       /** @var string|null */
+       protected $inputName;
+       /** @var string|null */
+       protected $inputPlaceholder;
+       /** @var array */
+       protected $input;
+       /** @var int|null */
+       protected $tagLimit;
 
        /**
         * @param array $config Configuration options
         *   - array $config['default'] Array of items to use as preset data
-        *   - array $config['name'] Name attribute (used in forms)
-        *   - array $config['placeholder'] Placeholder message for input
+        *   - string $config['name'] Name attribute (used in forms)
+        *   - string $config['placeholder'] Placeholder message for input
         *   - array $config['input'] Config options for the input widget
-        *   - number $config['tagLimit'] Maximum number of selected items
+        *   - int $config['tagLimit'] Maximum number of selected items
         */
        public function __construct( array $config = [] ) {
                parent::__construct( $config );
 
                // Properties
-               if ( isset( $config['default'] ) ) {
-                       $this->selectedArray = $config['default'];
-               }
-               if ( isset( $config['name'] ) ) {
-                       $this->inputName = $config['name'];
-               }
-               if ( isset( $config['placeholder'] ) ) {
-                       $this->inputPlaceholder = $config['placeholder'];
-               }
-               if ( isset( $config['input'] ) ) {
-                       $this->input = $config['input'];
-               } else {
-                       $this->input = [];
-               }
-               if ( isset( $config['tagLimit'] ) ) {
-                       $this->tagLimit = $config['tagLimit'];
-               }
+               $this->selectedArray = $config['default'] ?? [];
+               $this->inputName = $config['name'] ?? null;
+               $this->inputPlaceholder = $config['placeholder'] ?? null;
+               $this->input = $config['input'] ?? [];
+               $this->tagLimit = $config['tagLimit'] ?? null;
 
                $textarea = new MultilineTextInputWidget( array_merge( [
                        'name' => $this->inputName,
index 0df4cd0..5c2d290 100644 (file)
--- a/index.php
+++ b/index.php
@@ -30,6 +30,8 @@
  * @file
  */
 
+define( 'MW_ENTRY_POINT', 'index' );
+
 // Bail on old versions of PHP, or if composer has not been run yet to install
 // dependencies. Using dirname( __FILE__ ) here because __DIR__ is PHP5.3+.
 // phpcs:ignore MediaWiki.Usage.DirUsage.FunctionFound
index 6ba7796..e675889 100644 (file)
@@ -12,7 +12,7 @@
        "--exclude": [
                "resources/src/jquery.tablesorter",
                "resources/src/jquery.tipsy",
-               "resources/src/jquery/jquery.color.js",
+               "resources/src/jquery.color/jquery.color.js",
                "resources/src/jquery/jquery.highlightText.js",
                "resources/src/jquery/jquery.mw-jump.js",
                "resources/src/mediawiki.base/legacy.wikibits.js",
index 3508483..7d93d5b 100644 (file)
        "tog-useeditwarning": "حذّرني عندما أغادر تحرير صفحة فيها تغييرات لم أحفظها",
        "tog-prefershttps": "استخدم دائما اتصالا آمنا عند تسجيل الدخول",
        "tog-showrollbackconfirmation": "إظهار رسالة تأكيد عند النقر على رابط الاسترجاع",
+       "tog-requireemail": "تتطلب البريد الإلكتروني لإعادة تعيين كلمة المرور",
        "underline-always": "دائما",
        "underline-never": "أبدا",
        "underline-default": "وفق المظهر أو المتصفح",
        "undo-norev": "فشل في الرجوع عن التعديل حيث أنه غير موجود أو تم حذفه.",
        "undo-nochange": "يبدو أن التعديل قد تم التراجع عنه بالفعل.",
        "undo-summary": "الرجوع عن التعديل $1 بواسطة [[Special:Contributions/$2|$2]] ([[User talk:$2|نقاش]])",
+       "undo-summary-anon": "التراجع عن المراجعة $1 بواسطة [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "الرجوع عن المراجعة $1 التي أجراها مستخدمي مخفي",
        "cantcreateaccount-text": "إنشاء الحسابات من عنوان الأيبي هذا (<strong>$1</strong>) تم منعه بواسطة [[User:$3|$3]].\n\nالسبب المعطى بواسطة $3 هو <em>$2</em>",
        "cantcreateaccount-range-text": "إنشاء الحسابات من عناوين الآيبي في النطاق <strong>$1</strong>، التي تحتوي على الآيبي الخاص بك (<strong>$4</strong>)، قد منعها [[User:$3|$3]].\n\nالسبب المعطى بواسطة $3 هو <em>$2</em>",
        "prefs-help-email": "تحديد عنوان البريد الإلكتروني اختياري، ولكنه يلزم لإعادة تعيين كلمة المرور في حال نسيت كلمة المرور الخاصة بك.",
        "prefs-help-email-others": "يمكنك أيضا أن تسمح للآخرين الاتصال بك عن طريق وصلة في صفحة المستخدم أو نقاش المستخدم الخاصة بك. لا يكشف بريدك الإلكتروني عندما يراسلك أحد بهذه الطريقة، ولكن إذا قمت بالرد سيرى بريدك الإلكتروني.",
        "prefs-help-email-required": "عنوان البريد الإلكتروني مطلوب.",
+       "prefs-help-requireemail": "إذا تم تحديده، فسوف يرسل رسائل البريد الإلكتروني الخاصة بإعادة تعيين كلمة المرور فقط إذا كان الشخص الذي قام بإعادة الضبط قد قدم اسم المستخدم والبريد الإلكتروني لهذا الحساب.",
        "prefs-info": "المعلومات الأساسية",
        "prefs-i18n": "الترجمة",
        "prefs-signature": "التوقيع",
        "alreadyrolled": "لم يمكن استرجاع آخر تعديل ل[[$1]] بواسطة [[User:$2|$2]] ([[User talk:$2|نقاش]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]])؛\nشخص آخر عدل أو استرجع الصفحة بالفعل.\n\nآخر تعديل كان بواسطة [[User:$3|$3]] ([[User talk:$3|نقاش]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "ملخص التعديل كان:<em>$1</em>.",
        "revertpage": "استرجع تعديلات [[Special:Contributions/$2|$2]] ([[User talk:$2|نقاش]]) حتى آخر مراجعة ل[[User:$1|$1]]",
+       "revertpage-anon": "استرجع تعديلات [[Special:Contributions/$2|$2]] حتى آخر مراجعة بواسطة [[User:$1|$1]]",
        "revertpage-nouser": "استرجع تعديلات مستخدم مخفي حتى آخر مراجعة ل{{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "تم استرجاع تعديلات {{GENDER:$3|$1}}، حتى آخر نسخة بواسطة {{GENDER:$4|$2}}.",
        "sessionfailure-title": "فشل في الجلسة",
        "ipblocklist-legend": "إيجاد مستخدم ممنوع",
        "blocklist-userblocks": "أخفِ منع الحسابات",
        "blocklist-tempblocks": "أخفِ المنع المؤقت",
+       "blocklist-indefblocks": "إخفاء عمليات المنع غير المحددة",
        "blocklist-addressblocks": "أخفِ منع عنوان أيبي واحد",
        "blocklist-type": "النوع:",
        "blocklist-type-opt-all": "الكل",
index 469cb7e..c5a76e6 100644 (file)
        "editlink": "editar",
        "viewsourcelink": "ver fonte",
        "editsectionhint": "Editar seición: $1",
-       "toc": "Índiz",
+       "toc": "Conteníu",
        "showtoc": "amosar",
        "hidetoc": "anubrir",
        "collapsible-collapse": "Plegar",
index 1b3950f..52dfc22 100644 (file)
                        "Joseagush",
                        "Wandering ant",
                        "Kadek Ayu Sulastri",
-                       "Luh Gede Krismayanti"
+                       "Luh Gede Krismayanti",
+                       "Amire80"
                ]
        },
        "tog-underline": "Garis ring beten pranala:",
-       "tog-hideminor": "engkebang suntingan ring gentosan sane pinih anyar",
-       "tog-hidepatrolled": "engkebang suntingan mapatrol ring gentosan sane pinih anyar",
+       "tog-hideminor": "Engkebang uahan alit saking uahan sané mangkin",
+       "tog-hidepatrolled": "Engkebang uahan sané kapatroli saking uahan sané mangkin",
        "tog-newpageshidepatrolled": "engkebang lembar mapatrol saking saking kepahan lembar anyar",
        "tog-hidecategorization": "Engkebang kacané",
        "tog-extendwatchlist": "kembangang kepahan pangiwasan antuk nampilang samian panguwahan, nenten sane anyar kewanten",
@@ -73,7 +74,7 @@
        "mon": "Som",
        "tue": "Ang",
        "wed": "Bud",
-       "thu": "Wrs",
+       "thu": "Wra",
        "fri": "Suk",
        "sat": "San",
        "january": "Januari",
        "may": "Méi",
        "jun": "Jun",
        "jul": "Jul",
-       "aug": "Ags",
+       "aug": "Agu",
        "sep": "Sép",
        "oct": "Okt",
        "nov": "Nop",
        "dec": "Dés",
-       "january-date": "Januari $1",
-       "february-date": "Februari $1",
-       "march-date": "Maret $1",
-       "april-date": "April $1",
-       "may-date": "Mei $1",
-       "june-date": "Juni $1",
-       "july-date": "Juli $1",
-       "august-date": "Agustus $1",
-       "september-date": "September $1",
-       "october-date": "Oktober $1",
-       "november-date": "November $1",
-       "december-date": "Desember $1",
+       "january-date": "$1 Januari",
+       "february-date": "$1 Pébruari",
+       "march-date": "$1 Maret",
+       "april-date": "$1 April",
+       "may-date": "$1 Méi",
+       "june-date": "$1 Juni",
+       "july-date": "$1 Juli",
+       "august-date": "$1 Agustus",
+       "september-date": "$1 Séptémber",
+       "october-date": "$1 Oktober",
+       "november-date": "$1 Nopémber",
+       "december-date": "$1 Désémber",
        "period-am": "AM",
        "period-pm": "PM",
        "pagecategories": "{{PLURAL:$1|Kategori}}",
        "category_header": "Kaca ring ketegori \"$1\"",
        "subcategories": "Subkategori",
        "category-media-header": "Média ring kategori \"$1\"",
-       "category-empty": "\"mangkin, nenten madaging lembar utawi pekakas ring golongan puniki\"",
-       "hidden-categories": "{{plural:$1|punduhan sane kaengkebang| punduhan sane kaengkebang}}",
-       "hidden-category-category": "Kategori mengkeb",
-       "category-subcat-count": "{{PLURAL:$2| golongan puniki madue {{PLURAL:$1|$1 subkategori}} puniki, saking genepan $2.}}",
-       "category-article-count": "{{PLURAL:$2|golongan puniki madue{{PLURAL:$1|$1 lembar}}, saking total $2.}}",
+       "category-empty": "<em>Kategori puniki mangkin nénten madaging kaca utawi média.</em>",
+       "hidden-categories": "{{plural:$1|Kategori sané kaengkebang}}",
+       "hidden-category-category": "Kategori sané kaengkebang",
+       "category-subcat-count": "{{PLURAL:$2|Kategori iki wantah madué subkategori ring sor puniki|Kategori iki madué {{PLURAL:$1|subkategori|$1 subkategori}} ring sor puniki, saking $2 akéhnyané.}}",
+       "category-article-count": "{{PLURAL:$2|Kategori puniki wantah madué kaca ring sor puniki.|{{PLURAL:$1|Kaca|$1 kaca}} ring sor puniki wénten ring kategori puniki, saking $2 akéhnyané.}}",
        "category-file-count": "{{PLURAL:$2|golongan puniki madue{{PLURAL:$1|$1 lembar}}, saking total $2.}}",
        "listingcontinuesabbrev": "lant.",
        "index-category": "Lembar sane maindeks",
        "and": "&#32;miwah",
        "faq": "FAQ (pitaken sane jagi katakonang)",
        "actions": "Parilaksana",
-       "namespaces": "Genah wastan",
+       "namespaces": "Genah aran",
        "variants": "Varian",
        "navigation-heading": "Menu navigasi",
        "errorpagetitle": "Kaiwangan",
        "view": "Cingak",
        "view-foreign": "Cingak ring $1",
        "edit": "Uah",
-       "create": "Karyanin",
-       "create-local": "Icénin daging sané marupa paparan lokal",
+       "create": "Kardi",
+       "create-local": "Tambeh déskripsi lokal",
        "delete": "Usap",
        "viewdeleted_short": "Cingak {{PLURAL:$1|siki uahan sané kausapin|$1 uahan sané kausapin}}",
        "protect": "Saib",
        "personaltools": "Pekakas praragan",
        "talk": "Pabligbagan",
        "views": "Pakantenan",
-       "toolbox": "Pekakas",
+       "toolbox": "Piranti",
        "tool-link-emailuser": "Kirim surel ring {{GENDER:$1|pengguna}} puniki",
        "imagepage": "Cingak kaca berkas",
-       "mediawikipage": "Cingak kaca séwalapatra",
+       "mediawikipage": "Cingak kaca séwala",
        "templatepage": "Cingak kaca cétakan",
        "viewhelppage": "Cingak kaca wantuan",
        "categorypage": "Cingak kaca kategori",
        "pool-errorunknown": "Iwang sané durung kauningin",
        "aboutsite": "Indik {{SITENAME}}",
        "aboutpage": "Project:Indik",
+       "copyright": "Daging kasayagayang ring sor $1 ri tatkala nénten wénten uahan.",
        "copyrightpage": "{{ns:project}}:Hak cipta",
        "currentevents": "Kawéntenané mangkin",
        "currentevents-url": "Project:Kawéntenané mangkin",
        "privacypage": "Project:Awig-awig indik data praragan",
        "ok": "OK",
        "retrievedfrom": "Kapolihang saking \"$1\"",
-       "youhavenewmessages": "{{PLURAL:$3|Jero madué}} $1 ($2)",
-       "youhavenewmessagesfromusers": "{{PLURAL:$4|Ida dané madué}} $1 saking {{PLURAL:$3|$3 sang anganggé lianan}} ($2).",
+       "youhavenewmessages": "{{PLURAL:$3|Ragané madué}} $1 ($2)",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Ragané madué}} $1 saking {{PLURAL:$3|$3 sang anganggé lianan}} ($2).",
        "youhavenewmessagesmanyusers": "Jero madué $1 saking akéh sang anganggé ($2).",
-       "newmessageslinkplural": "{{PLURAL:$1|séwalapatra anyar abesik|999=séwalapatra anyar}}",
-       "youhavenewmessagesmulti": "Ida dané madué séwalapatra anyar ring $1",
+       "newmessageslinkplural": "{{PLURAL:$1|séwala anyar abesik|999=séwala anyar}}",
+       "newmessagesdifflinkplural": "$1 {{PLURAL:$1|uahan}}",
+       "youhavenewmessagesmulti": "Ragané madué séwala anyar ring $1",
        "editsection": "uah",
        "editold": "uah",
        "viewsourceold": "cingak wit",
        "nstab-special": "Kaca kusus",
        "nstab-project": "Kaca proyék",
        "nstab-image": "Depukan",
-       "nstab-mediawiki": "Séwalapatra",
+       "nstab-mediawiki": "Séwala",
        "nstab-template": "Cétakan",
        "nstab-help": "Kaca wantuan",
        "nstab-category": "Kategori",
        "nospecialpagetext": "<strong>Ida nagih kaca pinih luwih sane nenten patut.</strong>\n\nWacakan kaca pinih luwih dados kacingak ring [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Kaiwangan",
        "databaseerror": "Database kaluputan",
-       "databaseerror-query": "Kueri: $1",
+       "databaseerror-query": "Kuéri: $1",
        "databaseerror-function": "Pungsi: $1",
        "databaseerror-error": "Pelih: $1",
        "missing-article": "data utama nenten prasida nemu tulisan saking lembar sane sepatutne wenten, inggih punika  $1, $2\n\nindike puniki biasane keranayang olih pranala kaon nuju pabenahan sane dumun lembar sane sampun kaicalang\n\nyening nenten puniki sane ngranayang, ida dane minab sampun manggihin kaiwangang ring sajeroning piranti lunak.\nDurus sadokang indik puniki rin silih sinunggil anak \n\n[[Special:ListUsers/sysop|Pengurus]], antuk ngetik alamat URL sane katuju",
        "badtitletext": "Judul halaman sane katagih nenten patut, kosong, atau judul antarbahasa atau antarwiki yang salah sambung.\n\nmurda lembar sane kaarsa nenten sida kaedengang, kosong, utawi murda murda antarbasa utawi antarwiki sane iwang",
        "viewsource": "Cingak wit",
        "viewsource-title": "Cingak wit saking $1",
-       "viewsourcetext": "Jero dados nyingakin miwah nurun wit kaca puniki.",
+       "viewsourcetext": "Ragané dados nyingakin miwah nurun wit saking kaca puniki.",
        "yourname": "Peséngan sang anganggé:",
        "userlogin-yourname": "Peséngan sang anganggé",
-       "userlogin-yourname-ph": "Dagingin peséngan sang anganggé jero",
+       "userlogin-yourname-ph": "Dagingin peséngan sang anganggé ragané",
        "yourpassword": "Kruna sandi:",
        "userlogin-yourpassword": "Kruna sandi",
-       "userlogin-yourpassword-ph": "Dagingin kruna sandi jero",
+       "userlogin-yourpassword-ph": "Dagingin kruna sandi ragané",
        "createacct-yourpassword-ph": "Dagingin kruna sandi",
        "yourpasswordagain": "jumunin kruna sandi",
        "createacct-yourpasswordagain": "Mastiang kruna kunci",
        "notloggedin": "Durung manjing log",
        "userlogin-noaccount": "Durung madué akun?",
        "userlogin-joinproject": "Nyarengin {{SITENAME}}",
-       "createaccount": "Karyanin akun",
+       "createaccount": "Kardi akun",
        "userlogin-resetpassword-link": "Engsap ring kruna kunci?",
        "userlogin-helplink2": "Wantuan indik manjing log",
-       "createacct-emailoptional": "Alamat email (becikang kadagingin)",
-       "createacct-email-ph": "Dagingin alamat email jero",
-       "createacct-submit": "Karyanin akun jero",
-       "createacct-benefit-heading": "{{SITENAME}} kakaryanin olih anak sakadi jero.",
+       "createacct-emailoptional": "Alamat séwala éléktronik (opsional)",
+       "createacct-email-ph": "Dagingin alamat séwala éléktronik ragané",
+       "createacct-submit": "Kardi akun ragané",
+       "createacct-benefit-heading": "{{SITENAME}} kakaryanin antuk anak sakadi ragané.",
        "createacct-benefit-body1": "{{PLURAL:$1|uahan}}",
        "createacct-benefit-body2": "{{PLURAL:$1|kaca}}",
        "createacct-benefit-body3": "{{PLURAL:$1|sang anuut}} sané mangkin",
        "loginlanguagelabel": "Basa: $1",
        "pt-login": "Manjing log",
        "pt-login-button": "Manjing log",
-       "pt-createaccount": "Ngaryanin akun",
+       "pt-createaccount": "Kardi akun",
        "pt-userlogout": "Medal log",
        "botpasswords-label-create": "Ngae",
        "botpasswords-label-cancel": "Wangdé",
        "botpasswords-label-resetpassword": "Nyumu kruna sandi",
        "resetpass-submit-cancel": "Wangdé",
        "passwordreset": "Nyumu kruna sandi",
-       "bold_sample": "teks puniki mesurat tebel",
-       "bold_tip": "teks puniki mesurat tebel",
+       "bold_sample": "Suratan tebel",
+       "bold_tip": "téks puniki mesurat tebel",
        "italic_sample": "teks puniki masurat sendeh",
        "italic_tip": "teks puniki masurat sendeh",
        "link_sample": "murda pranala",
        "link_tip": "pranala tengah",
        "extlink_sample": "http://www.example.com murda pranala",
        "extlink_tip": "pranala sisi (sampunang lali kakawitin http://)",
-       "headline_sample": "teks murda",
+       "headline_sample": "téks murda",
        "headline_tip": "subgolongan undag 2",
        "nowiki_sample": "lebuang teks sane nenten jagi keformat ring driki",
        "nowiki_tip": "campahang format wiki",
        "image_tip": "cantumin pupulan",
        "media_tip": "Pranala depukan",
-       "sig_tip": "tanda tangan ida dane sareng tanda waktu",
+       "sig_tip": "tanda tangan ida dané sareng tanda waktu",
        "hr_tip": "garis horizontal",
        "summary": "Ringkesan:",
        "minoredit": "Puniki uahan alit",
-       "watchthis": "tinjo lembar puniki",
+       "watchthis": "Awasin kaca puniki",
        "savearticle": "Raksa kaca",
        "publishpage": "Terbitang kaca",
        "savearticle-start": "Raksa kaca...",
        "publishpage-start": "Terbitang kaca…",
-       "preview": "tayangan sadurungnyane",
-       "showpreview": "Sinahang preview",
+       "preview": "Pracingak",
+       "showpreview": "Édengang pracingak",
        "showdiff": "Cingak uahan",
        "anoneditwarning": "<strong>Pingetan:</strong> Ida dané nénten kacatet ngranjing. Alamat IP ida dané jagi kacatet ring sejarah (indik sané dumunan) ring lembar puniki. Yening ida dane <strong>[$1 log in]</strong> utawi <strong>[$2 create an account]</strong>, your edits will be attributed to your username, along with other benefits.",
+       "blockedtext": "<strong>Peséngan penganggé utawi genah IP ragané kablokir .</strong>\n\nBlokir puniki kalaksanayang olih $1.\nKablokir krana <em>$2</em>.\n\n* Kablokir saking: $8\n* Blokir kadaluwarsa ring: $6\n* Tetujon ngablokir: $7\n\nRagané dados ngubungin $1 utawi [[{{MediaWiki:Grouppage-sysop}}|prajuru]] antuk mabligbagin.\nRagané nénten dados nganggén fitur puniki \"{{int:emailuser}}\" sajabaning ragané sampun ngranjingang email sané patut ring [[Special:Preferences|pustaka]] tur ragané nénten kablokir antuk nganggén\nGenah IP ragané sané pinih anyar inggih punika $3, tur ID pamblokiran inggih punika #$5.\nTulung genahang silih sinunggil utawi kalih pidarta ring pitakén sané kakaryanin.",
        "loginreqlink": "manjing log",
        "newarticle": "(Anyar)",
        "newarticletext": "ida dane ngiring pranala nuju lembar sane durung wenten. yening jagi ngaryanang lembar punika, ketik daging lembar ring kotak sane wenten ring beten puniki. (cingak [$1 lembar wantuan] anggen wacana salanturnyane). yening ida dane nenten nyelapang neked ring lembar puniki, klik tombol \"back\" ring \"penjelajah web\" ida dane.",
-       "noarticletext": "mangkin nenten wenten teks ring lembar puniki. ida dane prasida [[Special:Search/{{PAGENAME}}|ngrereh murda nganggen lembar puniki]] ring lembar-lembar sane lianan, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ngrereh log sane mapaiketan], utawi [{{fullurl:{{FULLPAGENAME}}|action=edit}} nguwah lembar puniki]</span>.",
-       "noarticletext-nopermission": "mangkin nenten wenten teks ring lembar puniki. ida dane prasida [[Special:Search/{{PAGENAME}}|ngarereh murda anggen lembar puniki]] ring lembar-lembar sane lianan, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ngarereh log sane mapaiketan], utawi [{{fullurl:{{FULLPAGENAME}}|action=edit}} ngubah lembar puniki]</span>.",
+       "anontalkpagetext": "<em>Niki inggih punika kaca pabligbagan sang penganggé sané nénten nguningayang wasta utawi nénten nganggén wasta.</em> Nika mawinan penganggé punika patut nganggén genah IP sané mawentuk angka antuk manyihnayang.\nGenah IP punika prasida kaanggén sareng-sareng olih makudang-kudang panganggé sané lianan. \nYéning Ragané sang penganggé sané nénten mawasta tur marasa ngamolihang pidarta sané nénten patut, ngiring \n[[Special:CreateAccount|ngaryanin akun]] utawi [[Special:UserLogin|sang penganggé ngranjing log]] antuk ngelidin kabingungan saking sang penganggé sané lianan ring galah sané lianan.",
+       "noarticletext": "Mangkin nénten wénten suratan ring kaca puniki.\nRagané prasida [[Special:Search/{{PAGENAME}}|ngrereh murda kaca puniki]] ring kaca lianan,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ngrereh log sané mapaiketan],\nutawi [{{fullurl:{{FULLPAGENAME}}|action=edit}} ngardi kaca puniki]</span>.",
+       "noarticletext-nopermission": "Mangkin nénten wénten suratan ring kaca puniki.\nRagané prasida [[Special:Search/{{PAGENAME}}|ngrereh murda kaca puniki]] ring kaca lianan,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ngrereh log sané mapaiketan]</span>, nanging ragané tan kalugra ngardi kaca puniki.",
        "userpage-userdoesnotexist-view": "Akun sang anganggé \"$1\" nénten madaptar.",
-       "previewnote": "\"elingang yening puniki wantah sane lintang.\" Panguwahan ida dane durung kasimpen!",
+       "clearyourcache": "<strong>Catetan:</strong>Sesampun karaksayang, Ragané patut ngentasin tembolok peramban wéb antuk nyingakin uahan.\n* <strong>Firefox/Safari:</strong> Tahan <em>Shift</em> ritatkala ngaklik <em>Reload</em>, utawi teken <em>Ctrl-F5</em> utawi <em>Ctrl-R</em> (<em>⌘-R</em> ring Mac)\n* <strong>Google Chrome:</strong> Teken <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> ring Mac)\n* <strong>Internet Explorer:</strong> Teken <em>Ctrl</em> ritatkala ngaklik <em>Refresh</em>, utawi teken <em>Ctrl-F5</em>\n* <strong>Opera:</strong> Ngranjing ka <em>Ménu → Pengaturan </em> (<em>Opera → Pustaka</em> ring Mac) Salanturnyané ka <em>Privacy & security → Clear browsing data → Cached images and files</em>.",
+       "previewnote": "<strong>Éling yéning puniki wantah pracingak.</strong>\nUahan ragané durung karaksa!",
        "continue-editing": "Magingsir ka genah ngauwah",
        "editing": "Nguahin $1",
        "creating": "Makarya $1",
        "editingsection": "Nguahin $1 (pahan)",
        "editingcomment": "Nguahin $1 (pahan anyar)",
        "templatesused": "{{PLURAL:$1|Citakan}} sané kaanggén ring kaca puniki:",
+       "templatesusedpreview": "{{PLURAL:$1|Citakan}} sané kaanggén ring pracingak puniki:",
        "template-protected": "(kasaibin)",
        "template-semiprotected": "(semi-kasaibin)",
        "hiddencategories": "lembar niki inggih punika krama saking {{PLURAL:$1|1 golongan sane mengkeb|$1 golongan sane mengkeb}}",
+       "permissionserrors": "Pikobet lugra",
        "permissionserrorstext-withaction": "ida dané nénten madué kuasa ngranjing anggén $2, riantukan {{PLURAL:$1|alasan}} ring sor puniki:",
        "recreate-moveddeleted-warn": "\"pingetan\" ida dane ngawe malih lembar sane naenin maapus.'''\n\nmangda kayunin malih napike pantes lanturang suntingan ida dane. puniki log pengapusan lan pangisidan saking lembar puniki:",
        "moveddeleted-notice": "Kaca puniki sampun kausapin.\nAnggen pewarah, proteksi, lan pengisidan log saking lembar puniki cingakin pustaka beten.",
        "post-expand-template-inclusion-category": "lembar sane maukuran templat sane nglangkungin wates",
        "post-expand-template-argument-warning": "\"peminget\" lembar puniki madaging kiranglangkungnyane siki argumen templat anggen ukuran ekspansi sane kaliwat ageng. argumen-argumen punika sampun kacampahang.",
        "post-expand-template-argument-category": "lembar sane medaging argumen templat sane kacampahang",
+       "undo-failure": "Uwahan puniki nénten prasida kabalikang krana wénten konflik panguwahan antara.",
        "viewpagelogs": "Cingak log saking kaca puniki",
-       "currentrev-asof": "pabecikan sane anyar ring pinanggal$1",
+       "currentrev-asof": "Révisi sané pinih anyar ring $1",
        "revisionasof": "Uahan ri tatkala $1",
-       "revision-info": "Panguwahan per $1 olih {{GENDER:$6|$2}}$7",
+       "revision-info": "Révisi ri tatkala $1 antuk {{GENDER:$6|$2}}$7",
        "previousrevision": "← Uahan sadurungnyané",
        "nextrevision": "Uahan salanturnyané →",
        "currentrevisionlink": "Uahan sané mangkin",
        "cur": "mgkn",
        "last": "sdrg",
        "histlegend": "pilih kalih tombol radio lantur pecik tombol \"bandingang\" anggen ngebandingang indik lianan. klik siki tanggal anggen nyingak indik lianan lembar ring pinanggal punika.<br />(skr)= binanne saking indik lianan sane mangkin, (untat) = binanne saking indik lianan sane dumunan, '''k''' = panguwahan alit, '''b''' = panguwahan bot, → = panguwahan kepahan, ← = reringkesan otomatis",
-       "history-fieldset-title": "Nyaringin révisi",
+       "history-fieldset-title": "Saring révisi",
        "history-show-deleted": "wantah sane kaapus",
-       "histfirst": "pinih suwe",
+       "histfirst": "pinih sué",
        "histlast": "pinih anyar",
        "history-feed-title": "Babad uahan",
        "history-feed-description": "Babad uahan kaca puniki ring wiki",
        "mergelog": "Gabung log",
        "revertmerge": "tansida nyarengin",
        "history-title": "Babad uahan saking \"$1\"",
-       "difference-title": "$1: sane malianan ring revisi",
+       "difference-title": "Bina pantaraning révisi \"$1\"",
        "lineno": "Carik $1:",
        "compareselectedversions": "bandingang penguwahan sane kapilih",
        "editundo": "nguliang",
        "diff-empty": "(Nénten wénten sané malianan)",
        "diff-multi-sameuser": "({{PLURAL:$1|$1 revisi pantaraning}} olih pangawi sane pateh nenten kacumawisang)",
-       "searchresults": "asil pangrereh",
+       "diff-multi-otherusers": "({{PLURAL:$1|Siki pamecikan pantaraning|$1 pamecikan pantaraning}} olih {{PLURAL:$2|siki pangangge lianan|$2 panggange}} nenten katampilan)",
+       "searchresults": "Asil pangrereh",
        "searchresults-title": "Asil pangrereh anggén \"$1\"",
        "prevn": "{{PLURAL:$1|$1}} sadurungnyané",
        "nextn": "{{PLURAL:$1|$1}} salanturnyané",
        "prev-page": "kaca sadurungnyané",
-       "prevn-title": "$1 {{PLURAL:$1|asil}} sadurunge",
+       "prevn-title": "$1 {{PLURAL:$1|asil}} sadurungnyané",
        "nextn-title": "$1 {{PLURAL:$1|asil}} selanturnyane",
        "shown-title": "Sinahang $1 {{PLURAL:$1|asil}} per kaca",
        "viewprevnext": "Cingak ($1 {{int:pipe-separator}}$2)($3)",
        "searchmenu-exists": "wenten lembar sane mamurda \"[[:$1]]\" ring wiki puniki. {{PLURAL:$2|0=| cingakin taler asil rerehan lianan sane kapolihang}}",
-       "searchmenu-new": "<strong> ngawi lembar \"[[:$1]] ring wiki puniki </ strong>! {{{{PLURAL:$2|}}| 0 = | cingak teler lembar sane kapolihang ring pangreregan | cingak taler asil pangrerehan sane kapolihang}}",
+       "searchmenu-new": "<strong>Kardi kaca \"[[:$1]]\" ring wiki puniki!</strong> {{PLURAL:$2|0=|Taler cingak kaca sané temunin ragané.|Taler cingak asil pangrereh.}}",
        "searchprofile-articles": "Kaca daging",
-       "searchprofile-images": "multimedia",
+       "searchprofile-images": "Multimédia",
        "searchprofile-everything": "Samian",
-       "searchprofile-advanced": "lanturane",
+       "searchprofile-advanced": "Lanturan",
        "searchprofile-articles-tooltip": "Rereh ring $1",
        "searchprofile-images-tooltip": "Rereh depukan",
-       "searchprofile-everything-tooltip": "pangrereh ring samian isi (taler lembar wecana)",
-       "searchprofile-advanced-tooltip": "Rereh ring genah wastan sané kapilih",
+       "searchprofile-everything-tooltip": "Rereh ring samian daging (rumasuk kaca pabligbagan)",
+       "searchprofile-advanced-tooltip": "Rereh ring genah aran sané kapilih",
        "search-result-size": "$1 ({{PLURAL:$2|1 kruna|$2 kruna}})",
        "search-result-category-size": "{{PLURAL:$1|1 krama|$1 krama}}({{PLURAL:$2|1  subgolongan|$2 subgolongan}}, {{PLURAL:$3|1 pupulan|$3 pupulan}})",
        "search-redirect": "(gingsiran saking $1)",
        "search-section": "(pahan $1)",
        "search-file-match": "(anut ring daging depukan)",
-       "search-suggest": "minab sane kearsaang $1",
+       "search-suggest": "Minab sané aptiang ragané: $1",
        "searchrelated": "paiketan",
        "searchall": "samian",
        "search-showingresults": "{{PLURAL:$4|Asil <strong>$1</strong> of <strong>$3</strong>|Asil-asil <strong>$1 – $2</strong> saking <strong>$3</strong>}}",
-       "search-nonefound": "nenten wenten asil sane caklek ring arsa",
+       "search-nonefound": "nénten wénten asil sané caklek ring arsa",
        "powersearch-ns": "Rereh ring genah wastan:",
-       "mypreferences": "Preferensi",
+       "mypreferences": "Préferénsi",
        "prefs-user-pages": "Kaca sang anganggé",
        "saveprefs": "Raksa",
        "prefs-editing": "Nguahin",
        "group-bot": "Bot",
        "group-sysop": "Prajuru",
        "grouppage-bot": "{{ns:project}}:Bot",
+       "grouppage-sysop": "{{ns:project}}:Prajuru",
        "right-edit": "Uah kaca",
-       "right-writeapi": "nganggén API sasuratan",
+       "right-writeapi": "Anggé API sasuratan",
        "right-delete": "Usap kaca",
        "right-editprotected": "Uah kaca sané kasaibin \"{{int:protect-level-sysop}}\"",
        "grant-createeditmovepage": "Karyanin, uah, miwah gingsirang kaca",
        "grant-editprotected": "Uah kaca sané kasaibin",
+       "grant-rollback": "Waliang uahan ring kaca",
        "newuserlogpage": "Log makarya sang anganggé",
+       "rightslog": "Log panguwahan hak ngaksés",
        "action-read": "wacén kaca puniki",
        "action-edit": "uah kaca puniki",
        "action-createpage": "karyanin kaca puniki",
-       "action-createaccount": "karyanin akun sang anganggé puniki",
+       "action-createaccount": "kardi akun sang anganggé puniki",
        "action-delete": "usap kaca puniki",
        "action-deletedhistory": "cingak babad kaca sané kausapin",
        "action-browsearchive": "rereh kaca sané kausapin",
        "recentchanges-summary": "Track uahan sané mangkin ring wikiné indik kaca puniki.",
        "recentchanges-noresult": "Nénten wénten uahan ring galahnyané puniki sané anut sareng praciri puniki.",
        "recentchanges-feed-description": "molihang pagentosan anyar ring wiki ring \"umpan\" puniki",
-       "recentchanges-label-newpage": "Uahan puniki makarya kaca anyar",
+       "recentchanges-label-newpage": "Uahan puniki ngardi kaca anyar",
        "recentchanges-label-minor": "Punika uahan alit",
        "recentchanges-label-bot": "Uahan puniki kalaksanayang antuk bot",
        "recentchanges-label-unpatrolled": "Uahan puniki durung kapatroli",
        "rcshowhidemine-show": "Sinahang",
        "rcshowhidemine-hide": "Engkebang",
        "rcshowhidecategorization-show": "Sinahang",
-       "rclinks": "Edengang untat $1 gentosan anyar $2 dina kaping untat",
+       "rclinks": "Sinahang $1 uahan sané untat ring $2 dina sané lintang",
        "diff": "bina",
        "hist": "bbd",
        "hide": "Engkebang",
        "newpageletter": "A",
        "boteditletter": "b",
        "rc-change-size-new": "$1 {{PLURAL:$1|bita}} sasampun kauah",
-       "rc-enhanced-expand": "edengang rerincian",
-       "rc-enhanced-hide": "engkebang rerincian",
-       "rc-old-title": "witnyané kakaryanin pinaka \"$1\"",
+       "rc-enhanced-expand": "Sinahang rerincian",
+       "rc-enhanced-hide": "Engkebang rerincian",
+       "rc-old-title": "witnyané kakardi pinaka \"$1\"",
        "recentchangeslinked": "Uahan mapaiketan",
        "recentchangeslinked-toolbox": "Uahan mapaiketan",
        "recentchangeslinked-title": "Uahan sané mapaiketan $1",
-       "recentchangeslinked-summary": "lembar kautamayang puniki ngicenin kepahan penguwahan kaping untat ring lembar-lembar sana mapaiket. Lembar sane [[Special:Watchlist|ida dane iwasin]] mapinget antuk sesuratan tebel",
+       "recentchangeslinked-summary": "Dagingin aran kaca antuk nyingakin uahan ring kaca-kaca sané kasambung kaca punika. (Antuk nyingakin kapahan kategori, dagingin {{ns:category}}:Aran kategori). Uahan kaca-kaca ring [[Special:Watchlist|Pangawasan ragané]] kasurat <strong>tebel</strong>.",
        "recentchangeslinked-page": "Peséngan kaca:",
        "recentchangeslinked-to": "Sinahang uahan saking kaca-kaca sané linked kaca puniki",
        "upload": "Unggahang depukan",
        "listfiles": "Bacakan depukan",
        "file-anchor-link": "Depukan",
        "filehist": "Babad berkas",
-       "filehist-help": "klik ring pinanggal/galah anggen nyingakin pupulan niki rikala punika",
+       "filehist-help": "Klik ring tanggal/galah anggén nyingakin berkas puniki ri tatkala galah punika.",
        "filehist-deleteall": "usap samian",
-       "filehist-revert": "buwungang",
-       "filehist-current": "sané mangkin",
+       "filehist-revert": "wangdéang",
+       "filehist-current": "mangkin",
        "filehist-datetime": "Tanggal/Galah",
        "filehist-thumb": "Miniatur",
        "filehist-thumbtext": "miniatur anggen versi ring $1",
        "filehist-nothumb": "Tusing ade miniatur",
        "filehist-user": "Sang anganggé",
-       "filehist-dimensions": "ukuran",
-       "filehist-comment": "tureksa",
+       "filehist-dimensions": "Diménsi",
+       "filehist-comment": "Pasaur",
        "imagelinks": "Panganggén depukan",
        "linkstoimage": "{{PLURAL:$1|Kaca|$1 kaca}} ring sor puniki nganggén depukan puniki:",
+       "linkstoimage-more": "Langkungan saking $1 {{PLURAL:$1|kaca|kaca-kaca}} nganggén berkas puniki.\nPupulan puniki nyinahang {{PLURAL:$1|kaca kapertama nganggén pranala langsung|$1 kaca sané nganggén pranala langsung}} ka berkasé puniki\nA [[Special:WhatLinksHere/$2|pupulan sané jangkep]] taler kasayagayang.",
        "nolinkstoimage": "Nénten wénten kaca sané nganggén berkas puniki.",
        "linkstoimage-redirect": "$1 (gingsiran berkas) $2",
        "sharedupload-desc-here": "Depukan puniki mawit saking $1 lan minab kaanggén olih proyék-proyék sané lianan. Déskripsinnyané ring [$2 kaca déskripsi depukannyané] kaarahin ring ungkur puniki.",
        "filepage-nofile": "Nentén wénten berkas sané mamurda sakadi punika",
        "shared-repo-name-wikimediacommons": "Wikimedia Commons",
-       "upload-disallowed-here": "Jero nénten dados numpuk depukan puniki.",
+       "upload-disallowed-here": "Ragané nénten dados numpuk depukan puniki.",
        "filedelete": "Usap $1",
        "filedelete-submit": "Usap",
        "filedelete-success": "<strong>$1</strong> sampun kausapin.",
        "randompage": "Kaca ulah-aluh",
        "statistics": "Statistik",
        "statistics-articles": "Kaca daging",
+       "double-redirect-fixer": "Pamecikan pengalihan",
        "brokenredirects-edit": "uah",
        "brokenredirects-delete": "usap",
        "withoutinterwiki-submit": "Sinahang",
        "booksources": "Wit buku",
        "booksources-search-legend": "Rereh wit buku",
        "booksources-search": "Rereh",
+       "specialloguserlabel": "Panggange",
+       "speciallogtitlelabel": "Tetujon (Murda utawi {{ns:user}}:sang panganggé antuk penganggé)",
        "log": "Log",
        "logeventslist-submit": "Sinahang",
        "all-logs-page": "Makasami log publik",
+       "alllogstext": "Pupulan tampilan log makasami sané kasayagayang ring {{SITENAME}}.\nRagané dados ngalaksanayang watesan tampilan nganggén ngamilih soroh log, sang anganggé (sénsitif kapitalisasi), utawi murdan kaca (taler sénsitif kapitalisasi).",
+       "logempty": "Nenten katemonin entri log sane patut",
        "allpages": "Makasami kaca",
        "allarticles": "Makasami kaca",
        "allinnamespace": "Makasami kaca (genah wastan $1)",
        "allpagessubmit": "Lanturang",
        "allpages-bad-ns": "{{SITENAME}} nénten madué genah wastan \"$1\".",
-       "allpages-hide-redirects": "Ngengkebang pagingsirian",
-       "categories": "Golongan",
+       "allpages-hide-redirects": "Engkebang kaca gingsirian",
+       "categories": "Kategori",
        "categories-submit": "Sinahang",
        "deletedcontributions": "Pituut sang anganggé sané kausapin",
        "linksearch-ns": "Genah wastan:",
        "listusers-submit": "Sinahang",
        "listgrouprights-members": "kepahan krama",
        "emailuser": "email sane nganggo niki",
-       "emailmessage": "Séwalapatra:",
-       "watchlist": "kepahan peninjoan",
-       "mywatchlist": "kepahan peninjoan",
+       "emailmessage": "Séwala:",
+       "usermessage-editor": "Séwala sistem",
+       "watchlist": "Pangawasan",
+       "mywatchlist": "Pangawasan",
        "watchlistfor2": "Anggén $1 $2",
-       "watch": "cingak",
+       "watch": "Awasin",
        "unwatch": "tan sida maninjo",
-       "watchlist-details": "{{PLURAL:$1|$1 kaca}} wénten ring bacakan pantauan ida dané (rumasuk kaca pabligbagan).",
+       "watchlist-details": "{{PLURAL:$1|$1 kaca}} wénten ring Pangawasan ragané (rumasuk kaca pabligbagan).",
+       "wlheader-showupdated": "Kaca-kaca puniki sampun kauwah saking kunjungan ragané sané pinih untat, kasinahang sareng <strong>tebel</strong>.",
+       "wlnote": "Ring sor puniki {{PLURAL:$1|uahan sané pinih untat| <strong>$1</strong> uahan}} pinih untat {{PLURAL:$2|jam|<strong>$2</strong> jam}},ngantos $3, $4.",
        "watchlist-submit": "Sinahang",
        "wlshowhideminor": "uahan alit",
-       "watchlist-options": "milih kepahan peninjo",
+       "watchlist-options": "Opsi pangawasan",
        "enotif_reset": "Cihnayang makasami kaca sané sampun karauhin",
        "enotif_subject_deleted": "Kaca {{SITENAME}} $1 sampun {{GENDER:$2|kausap}} $2",
        "enotif_body_intro_deleted": "Kaca{{SITENAME}} $1 sampun {{GENDER:$2|kausapin}} ring $PAGEEDITDATE olih $2, cingak $3.",
        "historyaction-submit": "Sinahang uahan",
        "actioncomplete": "pelaksanan sampun wusan",
        "actionfailed": "pelaksana luput",
-       "dellogpage": "log pangapus",
+       "dellogpage": "Log pangusap",
+       "rollback-confirmation-yes": "Waliang",
        "rollback-confirmation-no": "Wangdé",
-       "rollbacklink": "mabalik",
-       "rollbacklinkcount": "balikang $1 {{PLURAL:$1|suratan}}",
+       "rollbacklink": "waliang",
+       "rollbacklinkcount": "waliang $1 {{PLURAL:$1|uahan}}",
        "changecontentmodel-title-label": "Murda kaca",
        "protectlogpage": "Log saiban",
        "protectedarticle": "nyaib \"[[$1]]\"",
+       "modifiedarticleprotection": "nguwah tingkatan panyambi antuk  \"[[$1]]\"",
        "protect-default": "Lugra makasami sang anganggé",
        "restriction-edit": "Uah",
        "restriction-move": "Gingsirang",
        "undelete": "Cingak kaca sané kausapin",
        "undeleterevisions": "$1 {{PLURAL:$1|uahan}} kausapin",
-       "undeletelink": "cingak/uliang",
+       "undeletelink": "cingak/waliang",
        "undeleteviewlink": "cingak",
        "undelete-search-title": "Rereh kaca sané kausapin",
-       "namespace": "Genah wastan:",
-       "invert": "uliang pilihan",
-       "tooltip-invert": "Centang kotak puniki mangdané ngengkebang lembar sané kauwah ring genah wastan sané kapilih (miwah genah wastan sané mapaiketan yéning kacentang)",
-       "namespace_association": "Genah wasta sané mapaiketan",
-       "tooltip-namespace_association": "Céntang kotak puniki anggén nagingin genah wasta pabligbagan utawi subjék sané mapaiketan sareng genah wasta sané kapilih",
+       "namespace": "Genah aran:",
+       "invert": "Waliang pilihan",
+       "tooltip-invert": "Céntang kotak puniki mangda ngengkebang uahan kaca ring genah aran sané kapilih (miwah genah aran sané mapaiketan yéning kacéntang)",
+       "namespace_association": "Genah aran sané mapaiketan",
+       "tooltip-namespace_association": "Céntang kotak puniki mangda marengang genah aran pabligbagan utawi subyék sané mapaiketan genah aran sané kapilih",
        "blanknamespace": "(Utama)",
        "contributions": "Pituut {{GENDER:$1|sang anganggé}}",
        "contributions-title": "Pituut sang anganggé $1",
        "mycontris": "Pituut",
        "anoncontribs": "Pituut",
-       "contribsub2": "antuk {{GENDER:$3|$1}} ($2)",
+       "contribsub2": "Antuk {{GENDER:$3|$1}} ($2)",
+       "nocontribs": "Nénten wénten uwahan sané patut sareng cihna punika.",
        "uctop": "sane mangkin",
        "month": "Saking sasih (miwah sadurungnyané)",
        "year": "Saking warsa (miwah sadurungnyané):",
-       "sp-contributions-blocklog": "log pemblokiran",
+       "sp-contributions-blocklog": "log pangempet",
        "sp-contributions-deleted": "pituut {{GENDER:$1|sang anganggé}} sané kausapin",
        "sp-contributions-uploads": "unggahan",
        "sp-contributions-logs": "log",
        "sp-contributions-talk": "pabligbagan",
        "sp-contributions-search": "Rereh pituut",
        "sp-contributions-username": "Alamat IP wiadin peséngan sang anganggé:",
-       "sp-contributions-toponly": "tampilang wantah panguwahan sane anyar",
-       "sp-contributions-newonly": "Tampilang wantah panguwahan sane anyar",
+       "sp-contributions-toponly": "Wantah édéngang uahan sané pinih anyar",
+       "sp-contributions-newonly": "Wantah édéngang uahan sané ngardi kaca",
        "sp-contributions-submit": "Rereh",
        "whatlinkshere": "Pranala iriki",
-       "whatlinkshere-title": "lembar-lembar sane maduwe pranala kaping \"$1\"",
+       "whatlinkshere-title": "Kaca sané kasambung ring \"$1\"",
        "whatlinkshere-page": "Kaca:",
        "linkshere": "lembar puniki maduwe pranala ke '''$2'''",
        "nolinkshere": "Nénten wénten kaca sané madué pranala ring <strong>$2</strong>.",
        "isredirect": "Kaca gingsiran",
        "istemplate": "sareng kasurat",
        "isimage": "pranala pupulan-pupulan",
-       "whatlinkshere-prev": "{{PLURAL:$1|sadurungnyane|$1 sadurungnyane}}",
-       "whatlinkshere-next": "{{PLURAL:$1|selanturnyane}}",
+       "whatlinkshere-prev": "{{PLURAL:$1|sadurungnyané|$1 sadurungnyané}}",
+       "whatlinkshere-next": "{{PLURAL:$1|salanturnyané|$1 salanturnyané}}",
        "whatlinkshere-links": "← pranala",
-       "whatlinkshere-hideredirs": "$1 pangalihan",
+       "whatlinkshere-hideredirs": "$1 kaca gingsiran",
        "whatlinkshere-hidetrans": "$1 transklusi",
        "whatlinkshere-hidelinks": "$1 pranala",
        "whatlinkshere-hideimages": "$1 pranala berkas",
-       "whatlinkshere-filters": "Panyaring",
+       "whatlinkshere-filters": "Panyaringan",
        "ipboptions": "2 jam:2 hours,1 dina:1 day,3 dina:3 days,1 minggu:1 week,2 minggu:2 weeks,1 sasih:1 month,3 sasih:3 months,6 sasih:6 months,1 taun:1 year,tanpa wates:infinite",
        "ipb-pages-label": "Kaca",
        "ipb-namespaces-label": "Genah wastan",
        "block-prevent-edit": "Nguahin",
-       "ipblocklist": "ngempetin sane nganggo",
+       "ipblocklist": "Sang anganggé sané kaempetin",
        "infiniteblock": "Nénten kawates",
        "blocklist-nousertalk": "tan prasida nguahin kaca pabligbagan praragan",
        "blocklist-editing-page": "kaca",
        "blocklist-editing-ns": "genah wastan",
-       "blocklink": "ngempetin",
+       "blocklink": "empet",
        "unblocklink": "ngicalang kaempetan",
-       "change-blocklink": "gentosin empetin",
+       "change-blocklink": "uah pangempet",
        "contribslink": "pituut",
-       "blocklogpage": "log pemblokiran",
+       "blocklogpage": "Log pangempet",
        "blocklogentry": "mlokir [[$1]] anggen pangwates galah $2$3",
+       "reblock-logentry": "nguwah blokiran aturan antuk [[$1]] sareng galah kadaluwarsa $2 $3",
        "block-log-flags-nocreate": "ngawe akun kaicalang",
+       "proxyblocker": "Sané ngablokir proxy",
        "movelogpage": "Log gingsiran",
-       "revertmove": "buwungang",
+       "revertmove": "wangdéang",
        "export": "ekspor lembar",
        "export-download": "Raksa pinaka berkas",
-       "allmessages": "Séwalapatra sistem",
+       "allmessages": "Séwala sistem",
        "allmessagesname": "pesengan",
        "allmessagesdefault": "teks lingga",
        "thumbnail-more": "Ngedénang",
        "thumbnail_error": "luput ngaryanin bentuk cenik $1",
        "import-interwiki-sourcepage": "Kaca wit:",
        "importlogpage": "Log impor",
-       "tooltip-pt-userpage": "Kaca {{GENDER:|sang anganggé jero}}",
-       "tooltip-pt-mytalk": "Kaca pabligbagan {{GENDER:|jero}}",
-       "tooltip-pt-preferences": "Preferensi {{GENDER:|jero}}",
+       "tooltip-pt-userpage": "Kaca {{GENDER:|sang anganggé ragané}}",
+       "tooltip-pt-mytalk": "Kaca pabligbagan {{GENDER:|ragané}}",
+       "tooltip-pt-preferences": "Préferénsi {{GENDER:|ragané}}",
        "tooltip-pt-watchlist": "kepahan-kepahan lembar sane katinjo titiang",
-       "tooltip-pt-mycontris": "Bacakan pituut {{GENDER:|jero}}",
-       "tooltip-pt-login": "Jero kaaptiang mangda manjing log; yadiastun nénten wajib",
+       "tooltip-pt-mycontris": "Bacakan pituut {{GENDER:|ragané}}",
+       "tooltip-pt-login": "Ragané kaaptiang mangda manjing log; yadiastun nénten wajib",
        "tooltip-pt-logout": "Medal log",
-       "tooltip-pt-createaccount": "Jero kaaptiang mangda makarya akun miwah manjing log; yadiastun nénten wajib",
+       "tooltip-pt-createaccount": "Ragané kaaptiang mangda ngardi akun miwah manjing log; yadiastun nénten wajib",
        "tooltip-ca-talk": "Pabligbagan indik kaca daging",
        "tooltip-ca-edit": "Uah kaca puniki",
-       "tooltip-ca-addsection": "nyumunin kepahan anyar",
-       "tooltip-ca-viewsource": "Kaca puniki kasaibin.\nJero wantah prasida nyingakin witnyané",
+       "tooltip-ca-addsection": "Wiwit bagian anyar",
+       "tooltip-ca-viewsource": "Kaca puniki kasaibin.\nRagané wantah prasida nyingakin witnyané",
        "tooltip-ca-history": "Uahan sadurungnyané saking kaca puniki",
        "tooltip-ca-protect": "Saib kaca puniki",
        "tooltip-ca-unprotect": "Uah saiban kaca puniki",
        "tooltip-ca-delete": "Usap kaca puniki",
        "tooltip-ca-move": "Gingsirang kaca puniki",
-       "tooltip-ca-watch": "Imbuhin kaca puniki ring bacakan pantauan ida dané",
-       "tooltip-ca-unwatch": "apus lembar niki ring daftar paninjoan ida dane",
+       "tooltip-ca-watch": "Tambeh kaca puniki ring pangawasan ragané",
+       "tooltip-ca-unwatch": "Usap kaca puniki saking pangawasan ragané",
        "tooltip-search": "Rereh ring {{SITENAME}}",
        "tooltip-search-go": "Rereh kaca sané mapeséngan pateh sakadi puniki yéning wénten",
        "tooltip-search-fulltext": "Rereh kaca sané madaging sesuratan puniki",
        "tooltip-t-permalink": "Pranala ajeg anggén révisinnyané kacané puniki",
        "tooltip-ca-nstab-main": "Cingak kaca daging",
        "tooltip-ca-nstab-user": "Cingak kaca sang anganggé",
-       "tooltip-ca-nstab-special": "Puniki kaca kusus tur nénten prasida kauwah",
+       "tooltip-ca-nstab-special": "Puniki kaca kusus tur nénten prasida kauah",
        "tooltip-ca-nstab-project": "Cingak kaca proyek",
        "tooltip-ca-nstab-image": "Cingak kaca depukannyané",
-       "tooltip-ca-nstab-mediawiki": "Cingak séwalapatra sistem",
+       "tooltip-ca-nstab-mediawiki": "Cingak séwala sistem",
        "tooltip-ca-nstab-template": "Cingak citakan",
        "tooltip-ca-nstab-help": "Cingak kaca wantuan",
        "tooltip-ca-nstab-category": "Cingak kaca kategori",
        "tooltip-minoredit": "pingetin puniki dados panguwahan kidik",
-       "tooltip-save": "Raksa uahan jero",
-       "tooltip-preview": "Pagentosan sane dumun duwen ida dane, mangda anggen niki sadurung jagi nyimpen!",
-       "tooltip-diff": "Sinahang uahan sané karyanin jero ring sesuratannyané",
-       "tooltip-compareselectedversions": "cingak binane makekalih kepahan lembar sane kasudi",
-       "tooltip-watch": "imbuhin lembar niki ring daftar paninjoan ida dane",
-       "tooltip-rollback": "\"nguliang\" muwungan jagi ngabecikang ring lembar puniki nuju haturan sane untat ngangge apisan klik",
+       "tooltip-save": "Raksa uahan ragané",
+       "tooltip-preview": "Pracingak uahan ragané. Rarisang nganggén pracingak puniki sadurung ngraksa.",
+       "tooltip-diff": "Édéngang uahan sané karyanin ragané ring suratannyané",
+       "tooltip-compareselectedversions": "Cingak bina pantaraning kalih révisi kaca puniki sané kapilih",
+       "tooltip-watch": "Tambeh kaca puniki ring pangawasan ragané",
+       "tooltip-rollback": "\"Waliang\" wantah ngwangdéang uahan kontributor sané pinih untat ring kaca puniki antuk klik apisan",
        "tooltip-undo": "\"nguliang\" ngabuwungin jagi ngabecikang niki lan ngagah kotak mecikang ngangge mode pratayang. dasar ipun prasida kaimbuhin ring kotak pamicutet",
        "tooltip-summary": "Dagingin ringkesan",
-       "simpleantispam-label": "Pamariksa anti-spam.\nPuniki <strong>wenten</strong> kaisi!",
+       "simpleantispam-label": "Panuréksa anti-spam.\n<strong>Sampunang</strong> nagingin puniki!",
        "pageinfo-title": "Pidarta indik \"$1\"",
        "pageinfo-header-basic": "Pidarta kaca",
        "pageinfo-header-edits": "Babad uahan",
        "pageinfo-header-restrictions": "Saiban kaca",
-       "pageinfo-header-properties": "Properti suratan",
-       "pageinfo-display-title": "Edengang judul",
+       "pageinfo-header-properties": "Properti kaca",
+       "pageinfo-display-title": "Murda tampilan",
+       "pageinfo-default-sort": "Kunci urut sané baku",
        "pageinfo-length": "Dawannyané kaca (ring bita)",
        "pageinfo-namespace": "Genah wastan",
        "pageinfo-article-id": "ID kaca",
        "pageinfo-language": "Basa ring daging kaca",
        "pageinfo-content-model": "Modél antuk daging kaca",
+       "pageinfo-robot-policy": "Kaindéksang antuk robot",
        "pageinfo-robot-index": "Kalugra",
        "pageinfo-robot-noindex": "Tan kalugra",
-       "pageinfo-watchers": "Akéh nomér sané negdeg kaca",
+       "pageinfo-watchers": "Akéh sané ngawasin kaca",
+       "pageinfo-few-watchers": "Kirang saking $1 {{PLURAL:$1|sané ngawasin}}",
        "pageinfo-redirects-name": "Akéh nomer sané magingsir ka kaca puniki",
        "pageinfo-subpages-name": "Kapahan kaca saking kaca puniki",
+       "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|kaalihang}}; $3 {{PLURAL:$3|nénten-kaalihang}})",
        "pageinfo-firstuser": "Sang makarya kaca",
-       "pageinfo-firsttime": "Galah ritatkala ngripta kaca",
+       "pageinfo-firsttime": "Tanggal ngardi kaca",
        "pageinfo-lastuser": "Panguwah sané pinih anyar",
        "pageinfo-lasttime": "Galah antuk uahan sané pinih anyar",
-       "pageinfo-edits": "Akéh nomer sané kauwah",
+       "pageinfo-edits": "Akéh uahan",
        "pageinfo-authors": "Akéh nomer makasami antuk panyurat sané lianan",
        "pageinfo-recent-edits": "Akéh nomer sané kauwah (ring $1 sané sampun lintang)",
        "pageinfo-recent-authors": "Akéh nomer antuk panyurat sané lianan",
+       "pageinfo-magic-words": "{{PLURAL:$1Kruna}} sakti ($1)",
+       "pageinfo-hidden-categories": "{{PLURAL:$1|Kategori}} sané kaengkebang ($1)",
+       "pageinfo-templates": "Katranslusi {{PLURAL:$1|template|templates}} ($1)",
        "pageinfo-toolboxlink": "Pidarta kaca",
        "pageinfo-contentpage": "Kapeték dados kaca daging",
        "pageinfo-contentpage-yes": "Inggih",
+       "patrol-log-page": "Log patroli",
        "previousdiff": "← Uahan sadurungnyané",
        "nextdiff": "Uahan sané pinih anyar →",
        "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|kaca}}",
        "svg-long-desc": "Berkas SVG, jimbarnyané $1 × $2 piksel, agengnyané berkas: $3",
        "show-big-image": "Depukan sujati",
        "show-big-image-preview": "Agengnyané pratuduh puniki: $1.",
-       "show-big-image-other": "{{PLURAL:$2|Resolusi}} iianan: $1.",
+       "show-big-image-other": "{{PLURAL:$2|Résolusi}} lianan: $1.",
        "show-big-image-size": "$1 × $2 piksel",
        "sunday-at": "Redite jam $1",
        "bad_image_list": "bentukne sekadi puniki:\n\nwantah kepahan daftar ( baris sane kakawitin anggen tanda *) sane kaitung pranala kapertama ring baris mangda pranala ring berkas sane kaon.\nPranala-Pranala sane selanturnyane ring baris sane pateh kamanahang antuk pinangging, inggih punika lembar sane prasida ngedengang berkas punika.",
        "metadata": "Métadata",
        "metadata-help": "pupulan puniki madaging wacana imbuhan minab sane kaimbuhin olih kamera digital utawi scanner sane kaanggen antuk ngawi atawi \"mendigitalisasi\" pupulan. Yening pupulan niki sampun taen kautak-atik, rerincine sane wenten minab nenten samian nyiriang wacan saking gambar sane sampun kautak-atik niki.",
-       "metadata-fields": "Widang métadata gambar sané kacantumang ring séwalapatra puniki jagi kalebuang ring tampilan kaca gambar ri tatkala tabél métadata kacenikang.\nSané lianan jagi kasenetang.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
+       "metadata-fields": "Widang métadata gambar ring séwala puniki jagi kalebuang ring tampilan kaca gambar ri tatkala tabél métadata kacenikang.\nSané lianan jagi kasenetang.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
        "namespacesall": "samian",
        "monthsall": "samian",
        "confirmemail_invalidated": "Konfirmasi alamat email kawangdéang",
        "table_pager_prev": "Kaca sadurungnyané",
        "watchlisttools-clear": "Ngicalang pupulan sané sampun karauhin",
        "watchlisttools-view": "Cingak uahan sane relevan",
-       "watchlisttools-edit": "Cingak miwah uah bacakan pantauan",
-       "watchlisttools-raw": "Uah kepahan paninjo mentah",
+       "watchlisttools-edit": "Cingak miwah uah pangawasan",
+       "watchlisttools-raw": "Uah pangawasan matah",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|pabligbagan]])",
        "duplicate-defaultsort": "pingetan: sereg pangurutan lingga \"$2\" nyampahang sereg pangurutan lingga sadurunge \"$1\"",
        "version-specialpages": "Kaca kusus",
+       "redirect": "Pengalihan manut bacakan ID , panggage, kaca, pamecikan, utawi log",
+       "redirect-summary": "Kaca istimewa puniki kaglingsiran (manut wastan bacakannyane),kaca (manut pamecikan), utawi kacan pangangge (manut ID nomer panganggenyane). Kawigunan:\n[[{{#Special:Redirect}}/file/Example.jpg]], [[{{#Special:Redirect}}/revision/328429]], atau [[{{#Special:Redirect}}/user/101]].",
        "redirect-submit": "Nglanturang",
        "redirect-lookup": "Rereh:",
        "redirect-value": "Aji:",
        "redirect-file": "Wastan berkas",
        "specialpages": "Kaca kusus",
        "external_image_whitelist": "#banggiang baris niki sapunapi kawentenanne<pre>\n#anggen fragmen akspresi reguler (wantah kepahan ring kekelaih//) ring sor puniki\n#fragmen-fragmen puniki jagi kaadungang sareng URL saking gambar-gambar eksternal (sane kasambungang langsung)\n#fragmen sane adung jagi katampilang dados gambar, sisanne wantah dados pranala kewanten\n#baris sane kakawitin antuk # jagi kadadosang baris komentar\n#niki nenten ngabinayang aksara ageng lan alit\n#genahang samian fragmen ekspresi reguler ring sor baris puniki. banggiang baris niki sapunapi kawentennane</pre>",
-       "tag-filter": "filter [[Special:Tags|tag]]:",
+       "tag-filter": "Panyaring [[Special:Tags|tag]]:",
        "tag-list-wrapper": "[[Special:Tags|{{PLURAL:$1|Tag}}]]: $2",
+       "tag-mw-rollback": "Waliang",
+       "tag-mw-rollback-description": "Uahan sané ngwaliang uahan sadurungnyané nganggén pranala waliang",
        "tags-active-yes": "Inggih",
        "tags-active-no": "Nénten",
        "tags-edit": "uah",
        "tags-delete-title": "Usap tag",
        "compare-page2": "Kaca 2",
        "logentry-delete-delete": "$1 {{GENDER:$2|ngusapin}} kaca $3",
-       "revdelete-content-hid": "dagingnyané kaengkebang",
+       "logentry-delete-restore": "$1 {{GENDER:$2|ngwalikan}} kaca $3 ($4)",
+       "logentry-delete-revision": "$1 {{GENDER:$2|mauah}} kaca utama {{PLURAL:$5|$5  pamecikan}} ring kaca $3: $4",
+       "revdelete-content-hid": "daging kaengkebang",
        "logentry-move-move": "$1 {{GENDER:$2|ngingsirang}} kaca $3 ring $4",
-       "logentry-newusers-create": "Akun sang anganggé $1 {{GENDER:$2|kakaryanin}}",
-       "logentry-newusers-autocreate": "Akun sang anganggé $1 {{GENDER:$2|kakaryanin}} otomatis",
+       "logentry-move-move-noredirect": "$1 {{GENDER:$2|maglisiran}} kaca $3 ka $4 tur nenten ngawe pengalihan",
+       "logentry-move-move_redir": "$1 {{GENDER:$2|maglisiran}} kaca $3 ka $4 tur nenten ngawe pengalihan",
+       "logentry-patrol-patrol-auto": "$1 otomatis {{GENDER:$2|kacihnayang}} sampun kabecikang $4 saking kaca $3 kaawasin",
+       "logentry-newusers-create": "Akun sang anganggé $1 {{GENDER:$2|kakardi}}",
+       "logentry-newusers-autocreate": "Akun sang anganggé $1 {{GENDER:$2|kakardi}} otomatis",
        "logentry-protect-protect": "$1 {{GENDER:$2|nyaibin}} $3 $4",
        "logentry-upload-upload": "$1 {{GENDER:$2|ngunggahang}} $3",
        "logentry-upload-overwrite": "$1 {{GENDER:$2|ngunggahang}} vèrsi anyar saking $3",
        "feedback-cancel": "Wangdé",
-       "feedback-message": "Séwalapatra:",
+       "feedback-message": "Séwala:",
        "searchsuggest-search": "Rereh ring {{SITENAME}}",
        "duration-days": "$1 {{PLURAL:$1|rahina}}",
        "pagelanguage": "Uah basa ring kaca",
        "pagelang-nonexistent-page": "Kaca $1 nénten wénten.",
        "mw-widgets-abandonedit-keep": "Lanturang nguah",
+       "randomrootpage": "Kaca pinih dasar sane mabrarakan",
        "log-action-filter-protect-protect": "Saiban",
        "log-action-filter-protect-move_prot": "Ngingsirang saiban"
 }
index bc5c403..1a0775b 100644 (file)
        "sessionfailure": "Изглежда има проблем със сесията ви;\nдействието беше отказано като предпазна мярка срещу крадене на сесията.\nМоля, изпратете формуляра повторно.",
        "changecontentmodel": "Промяна на модела на съдържанието на страница",
        "changecontentmodel-legend": "Промяна на модела на съдържанието",
-       "changecontentmodel-title-label": "Заглавие на страницата",
-       "changecontentmodel-model-label": "Нов модел на съдържанието",
+       "changecontentmodel-title-label": "Заглавие на страницата:",
+       "changecontentmodel-model-label": "Нов модел на съдържанието:",
        "changecontentmodel-reason-label": "Причина:",
        "changecontentmodel-submit": "Променяне",
        "changecontentmodel-success-title": "Моделът на съдържанието беше променен",
        "dberr-again": "Изчакайте няколко минути и опитайте да презаредите.",
        "dberr-info": "(Няма достъп до базата от данни: $1)",
        "dberr-info-hidden": "(Няма връзка със сървъра на базата данни)",
-       "htmlform-invalid-input": "Има проблеми с част от въведения от вас вход",
+       "htmlform-invalid-input": "Има проблеми с част от въведения от вас текст",
        "htmlform-select-badoption": "Посочената от вас стойност не е валидна алтернатива.",
        "htmlform-int-invalid": "Въведената от вас стойност не е цяло число.",
        "htmlform-float-invalid": "Посочената стойност не е число.",
        "htmlform-int-toolow": "Посочената от вас стойност е под минимално допустимата $1.",
        "htmlform-int-toohigh": "Посочената от вас стойност надхвърля максимално допустимата $1.",
-       "htmlform-required": "Тази стойност се изисква",
+       "htmlform-required": "Тази стойност е задължителна.",
        "htmlform-submit": "Изпращане",
        "htmlform-reset": "Отказване на промените",
        "htmlform-selectorother-other": "Друга",
index a309520..c5274a3 100644 (file)
@@ -87,6 +87,7 @@
        "tog-useeditwarning": "কোনো সম্পাদনা পাতা ত্যাগের সময় পরিবর্তনগুলি সংরক্ষিত না হয়ে থাকলে আমাকে সাবধান করা হোক",
        "tog-prefershttps": "অ্যাকাউন্টে প্রবেশ করার সময় সবসময় নিরাপদ সংযোগ ব্যবহার করুন",
        "tog-showrollbackconfirmation": "একটি রোলব্যাক লিঙ্ক ক্লিক করার সময় একটি নিশ্চিতকরণ বার্তা দেখান",
+       "tog-requireemail": "পাসওয়ার্ড পুনঃস্থাপন করার জন্য ইমেল প্রয়োজন",
        "underline-always": "সব সময়",
        "underline-never": "কখনো নয়",
        "underline-default": "আবরণ বা ব্রাউজারে যেমনভাবে নির্দিষ্ট করা আছে",
        "undo-norev": "সম্পাদনাটি বাতিল করা যাচ্ছেনা কারণ এটি আর নেই বা মুছে ফেলা হয়েছে।",
        "undo-nochange": "সম্পাদনাটি পূর্বেই বাতিল করা হয়েছে।",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|আলাপ]])-এর সম্পাদিত $1 নম্বর সংশোধনটি বাতিল করা হয়েছে",
+       "undo-summary-anon": "[[Special:Contributions/$2|$2]]-এর সম্পাদিত $1 নম্বর সংশোধনটি বাতিল করা হয়েছে",
        "undo-summary-username-hidden": "একজন লুকানো ব্যবহারকারীর করা $1 নং সংশোধনটি বাতিল করা হয়েছে",
        "cantcreateaccount-text": "[[User:$3|$3]] এই আইপি ঠিকানা('''$1''') থেকে অ্যাকাউন্ট সৃষ্টিতে বাধা দিয়েছেন।\n\n$3-এর দেয়া কারণ হল ''$2''",
        "cantcreateaccount-range-text": "[[User:$3|$3]] কর্তৃক আইপি ঠিকানার ব্যাপ্তি <strong>$1</strong>-এর মধ্যে অ্যাকাউন্ট তৈরি করা অবরুদ্ধ করা হয়েছে। যাতে আপনার আইপি ঠিকানাও (<strong>$4</strong>) রয়েছে। \n\n$3 কর্তৃক <em>$2</em> কারণ দেখানো হয়েছে।",
        "sessionfailure": "আপনার প্রবেশ সেশনে একটি সমস্যা হয়েছে বলে মনে হচ্ছে;\nসেশন হাইজ্যাক প্রতিরোধের উপায় হিসেবে এই কাজটি বাতিল করা হয়েছে।\nদয়া করে ফরমটি পুনরায় জমা দিন।",
        "changecontentmodel": "একটি পাতার বিষয়বস্তুর রূপ পরিবর্তন",
        "changecontentmodel-legend": "বিষয়বস্তুর রূপ পরিবর্তন করুন",
-       "changecontentmodel-title-label": "পাতার শিরোনাম",
+       "changecontentmodel-title-label": "পাতার শিরোনাম:",
        "changecontentmodel-current-label": "বর্তমান বিষয়বস্তুর রূপ:",
-       "changecontentmodel-model-label": "পাতার বিষয়বস্তুর প্রতিরূপ",
+       "changecontentmodel-model-label": "পাতার বিষয়বস্তুর প্রতিরূপ:",
        "changecontentmodel-reason-label": "কারণ:",
        "changecontentmodel-submit": "পরিবর্তন করুন",
        "changecontentmodel-success-title": "বিষয়বস্তুর প্রতিরূপ পরিবর্তিত হয়েছিলো",
        "move-subpages": "উপপাতা স্থানান্তর ($1টি পর্যন্ত)",
        "move-talk-subpages": "উপপাতার আলাপ পাতা স্থানান্তর ($1টি পর্যন্ত)",
        "movepage-page-exists": "$1 পাতাটি ইতিমধ্যেই বিদ্যমান এবং স্বয়ংক্রিয়ভাবে পুনর্লিখন করা সম্ভব নয়।",
+       "movepage-source-doesnt-exist": "$1 পাতাটির অস্তিত্ব নেই এবং স্থানান্তর করা যাবে না।",
        "movepage-page-moved": "$1 পাতাটি $2 পাতায় স্থানান্তর করা হয়েছে।",
        "movepage-page-unmoved": "$1 পাতাটি $2 -এ সরিয়ে নেওয়া সম্ভপর নয়।",
        "movepage-max-pages": "সর্বোচ্চ $1টি {{PLURAL:$1|উপপাতা}}স্থানান্তর করা হয়েছে এবং এর থেকে বেশি সংখ্যক পাতা সয়ংক্রিয়ভাবে স্থানান্তর সম্ভব নয়।",
index 34b49f5..e71e02f 100644 (file)
        "page_first": "یەکەمین",
        "page_last": "دوایین",
        "histlegend": "ھەڵبژاردنی جیاوازی: پیاچوونەوەکان بۆ ھەڵسەنگاندن دیاری بکە و ئینتەر یان دوگمەکەی خوارەوە لێبدە.<br />\nڕێنوێنی: '''({{int:cur}})''' = جیاوازی لەگەڵ دوایین پیاچوونەوە، '''({{int:last}})''' = جیاوازی لەگەڵ پیاچوونەوەی پێشووی، '''{{int:minoreditletter}}''' = دەستکاریی بچووک.",
-       "history-fieldset-title": "گەڕان بەدوای بەسەرداچوونەوەکان",
+       "history-fieldset-title": "پاڵاوتنی بەسەرداچوونەوەکان",
        "history-show-deleted": "تەنیا پێداچوونەوە سڕاوەکان",
        "histfirst": "کۆنترین",
        "histlast": "نوێترین",
        "recentchangeslinked-feed": "گۆڕانکارییە پەیوەندیدارەکان",
        "recentchangeslinked-toolbox": "گۆڕانکارییە پەیوەندیدارەکان",
        "recentchangeslinked-title": "گۆڕانکارییە پەیوەندیدارەکان بە \"$1\" ـەوە",
-       "recentchangeslinked-summary": "ناوی پەڕەک داخل بکە بۆ بینینی گۆڕانکارییەکانی ئەو پەڕانەی کە بەستەریان ھەیە بۆ ئەو پەڕەیە یان لەو پەڕەیەوە پەیوەست کراون. (بۆ بینینی ئەندامەکانی پۆلێک، پۆل:ناوی پۆلەکە داخل بکە). گۆڕانکارییەکانی پەڕەکانی [[Special:Watchlist|لیستی چاودێرییەکەت]] <strong>ئەستوورن</strong>.",
+       "recentchangeslinked-summary": "ناوی پەڕەک داخل بکە بۆ بینینی گۆڕانکارییەکانی ئەو پەڕانەی کە بەستەریان ھەیە بۆ ئەو پەڕەیە یان لەو پەڕەیەوە پەیوەست کراون. (بۆ بینینی ئەندامەکانی پۆلێک، {{ns:category}}:ناوی پۆلەکە داخل بکە). گۆڕانکارییەکانی پەڕەکانی [[Special:Watchlist|لیستی چاودێرییەکەت]] <strong>ئەستوورن</strong>.",
        "recentchangeslinked-page": "ناوی پەڕە:",
        "recentchangeslinked-to": "بەجێگەی ئەوە گۆڕانکارییەکانی ئەو پەڕانە نیشانبدە کە بەستەریان ھەیە بۆ پەڕەی دیاریکراو",
        "recentchanges-page-added-to-category": "[[:$1]] زیادکرا بۆ پۆل",
        "imagelinks": "بەکارھێنانی پەڕگە",
        "linkstoimage": "لەم {{PLURAL:$1|پەڕەی خوارەوە بەستەر دراوە|$1 پەڕەی خوارەوە بەستەر دراوە}} بۆ ئەم پەڕگە:",
        "linkstoimage-more": "زیاتر لە $1 {{PLURAL:$1|بەستەری لاپەڕە|بەستەری لاپەڕە}} بۆ ئەم پەڕگه.\nئەم لیستە {{PLURAL:$1|یەکەم لاپەڕەی بەستەرە|یەکەم لاپەڕە $1 بەستەرە}} بۆ تەنها یەم پەڕگە.\nهەروا [[Special:WhatLinksHere/$2|لیستی تەواو]] ئامادەی کەڵک وەرگرتنە.",
-       "nolinkstoimage": "Ú¾Û\8cÚ\86 Ù¾Û\95Ú\95Û\95Û\8cÛ\95Ú© Ù\86Û\8cÛ\8cÛ\95 Ú©Û\95 Ø¨Û\95ستÛ\95رÛ\8c Ú¾Û\95بÛ\8eت Ø¨Û\86 Ø¦Û\95Ù\85 Ù¾Û\95Ú\95Ú¯Û\95Û\8cÛ\95.",
+       "nolinkstoimage": "Ú¾Û\8cÚ\86 Ù¾Û\95Ú\95Û\95Û\8cÛ\95Ú© Ù\86Û\8cÛ\8cÛ\95 Ú©Û\95 Ø¦Û\95Ù\85 Ù¾Û\95Ú\95Ú¯Û\95Û\8cÛ\95 Ø¨Û\95کاربھÛ\8eÙ\86Û\8eت.",
        "morelinkstoimage": "[[Special:WhatLinksHere/$1|بەستەری زیاتر]] ببینە بۆ ئەم پەڕگە.",
        "linkstoimage-redirect": "$1 (ڕەوانەکەری پەڕگە) $2",
        "duplicatesoffile": "ئەم {{PLURAL:$1|پەڕگە دووبارەکرنەوەیەکی|پەڕگانە دووبارەکردنەوەی}} ئەم پەڕگەن ([[Special:FileDuplicateSearch/$2|وردەکاری زیاتر]]):",
        "uploadnewversion-linktext": "وەشانێکی نوێی ئەم پەڕگەیە بار بکە",
        "shared-repo-from": "لە لایەن $1",
        "shared-repo": "شوێنێکی هاوبەشی",
+       "shared-repo-name-wikimediacommons": "ویکیمیدیا کۆمنز",
        "upload-disallowed-here": "ناتوانی وەشانێکی نوێی ئەم پەڕگەیە بار بکەی.",
        "filerevert": "پێچەوانەکردنەوەی $1",
        "filerevert-legend": "پێچەوانەکردنەوەی پەڕگە",
index 15f5ee1..7975de7 100644 (file)
@@ -92,6 +92,7 @@
        "tog-useeditwarning": "Upozornit, když budu opouštět editaci bez uložení změn",
        "tog-prefershttps": "Po přihlášení vždy používat zabezpečené připojení",
        "tog-showrollbackconfirmation": "Při kliknutí na odkaz pro vrácení editace zobrazit žádost o potvrzení",
+       "tog-requireemail": "Pro obnovu hesla vyžadovat e-mail",
        "underline-always": "Vždy",
        "underline-never": "Nikdy",
        "underline-default": "Podle nastavení prohlížeče nebo vzhledu",
        "content-model-css": "CSS",
        "content-json-empty-object": "Prázdný objekt",
        "content-json-empty-array": "Prázdné pole",
+       "unsupported-content-model": "<strong>Varování:</strong> Model obsahu $1 není na této wiki podporován.",
+       "unsupported-content-diff": "Rozdíly obsahů s modelem $1 nejsou podporovány.",
+       "unsupported-content-diff2": "Rozdíly mezi obsahy s modely $1 a $2 nejsou na této wiki podporovány.",
        "deprecated-self-close-category": "Stránky s neplatnými sebeuzavírajícími HTML značkami",
        "deprecated-self-close-category-desc": "Stránka obsahuje neplatné sebeuzavírající HTML značky, například <code>&lt;b/></code> nebo <code>&lt;span/></code>. Jejich chování se v zájmu konzistence se specifikací HTML5 brzy změní, proto je jejich použití ve wikitextu zastaralé.",
        "duplicate-args-warning": "<strong>Upozornění:</strong> Stránka [[:$1]] volá [[:$2]] s více než jednou hodnotou parametru „$3“. Použije se jen poslední uvedená hodnota.",
        "undo-norev": "Tuto editaci není možné vrátit, protože neexistuje nebo byla smazána.",
        "undo-nochange": "Zdá se, že editace již byla zrušena.",
        "undo-summary": "Zrušena verze $1 od uživatele [[Special:Contributions/$2|$2]] ([[User talk:$2|diskuse]])",
+       "undo-summary-anon": "Zrušena verze $1 od uživatele [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Zrušena verze $1 od skrytého uživatele",
        "cantcreateaccount-text": "Zakládání nových účtů z této IP adresy (<strong>$1</strong>) bylo zablokováno {{GENDER:$3|uživatelem|uživatelkou}} [[User:$3|$3]].\n\n$3 uvádí toto zdůvodnění: <em>$2</em>",
        "cantcreateaccount-range-text": "Zakládání nových účtů z IP adres v rozsahu <strong>$1</strong>, který obsahuje i vaši IP adresu (<strong>$4</strong>), bylo zablokováno {{GENDER:$3|uživatelem|uživatelkou}} [[User:$3|$3]].\n\n$3 uvádí toto zdůvodnění: <em>$2</em>",
        "alreadyrolled": "Nelze vrátit zpět poslední editaci [[:$1]] od uživatele [[User:$2|$2]] ([[User talk:$2|diskuse]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]), protože někdo jiný již stránku editoval nebo vrátil tuto změnu zpět.\n\nPoslední editaci této stránky {{GENDER:$3|provedl|provedla|provedl uživatel}} [[User:$3|$3]] ([[User talk:$3|diskuse]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Shrnutí editace bylo: <em>$1</em>.",
        "revertpage": "Editace uživatele „[[Special:Contributions/$2|$2]]“ ([[User talk:$2|diskuse]]) vráceny do předchozího stavu, jehož autorem je „[[User:$1|$1]]“",
+       "revertpage-anon": "Editace uživatele „[[Special:Contributions/$2|$2]]“ vráceny do předchozího stavu, jehož autorem je „[[User:$1|$1]]“",
        "revertpage-nouser": "Editace skrytého uživatele vráceny do předchozího stavu, jehož {{GENDER:$1|autorem|autorkou}} je „[[User:$1|$1]]“",
        "rollback-success": "Editace {{GENDER:$3|uživatele|uživatelky}} $1 byly vráceny na poslední verzi od {{GENDER:$4|uživatele|uživatelky}} $2.",
        "sessionfailure-title": "Chyba relace",
        "ipblocklist-legend": "Hledat zablokovaného uživatele",
        "blocklist-userblocks": "Skrýt zablokované účty",
        "blocklist-tempblocks": "Skrýt dočasná zablokování",
+       "blocklist-indefblocks": "Skrýt zablokování do odvolání",
        "blocklist-addressblocks": "Skrýt blokování jedné IP adresy",
        "blocklist-type": "Typ:",
        "blocklist-type-opt-all": "Vše",
index 6ba40ff..bfed435 100644 (file)
        "checkbox-all": "Pêro",
        "checkbox-none": "Çıniyo",
        "checkbox-invert": "Dimlaşt ke",
-       "allpages": "Pêro peli",
+       "allpages": "Peli pêro",
        "nextpage": "Pela bahdoyêne ($1)",
        "prevpage": "Pela veri ($1)",
        "allpagesfrom": "Herfa kı pa liste bo:",
index e29eb53..9921c13 100644 (file)
@@ -4,7 +4,8 @@
                        "FRANCIS5091",
                        "FRANELYA",
                        "아라",
-                       "Macofe"
+                       "Macofe",
+                       "Tofeiku"
                ]
        },
        "tog-underline": "Mangagaris pioputan:",
        "editfont-monospace": "Pimato iso insir",
        "editfont-sansserif": "Pimato San-sorip",
        "editfont-serif": "Pimato Sorip",
-       "sunday": "Dautiwang",
-       "monday": "Dautonlu",
-       "tuesday": "Daumirod",
-       "wednesday": "Daumansa",
-       "thursday": "Dautadru",
-       "friday": "Daurudu",
-       "saturday": "Daukukuak",
-       "sun": "DTiw",
-       "mon": "DTon",
-       "tue": "DMir",
-       "wed": "DMad",
-       "thu": "DTad",
-       "fri": "DRud",
-       "sat": "DKua",
-       "january": "Tumilatok",
-       "february": "Tumansak",
-       "march": "Tugomot",
-       "april": "Tungiop",
-       "may_long": "Tumikat",
-       "june": "Tumahas",
-       "july": "Tumadas",
-       "august": "Tumagus",
-       "september": "Tumanom",
-       "october": "Tugumas",
-       "november": "Tumilau",
-       "december": "Tumomuhau",
+       "sunday": "Tiwang",
+       "monday": "Tontolu'",
+       "tuesday": "Mirod",
+       "wednesday": "Madsa",
+       "thursday": "Tadtaru",
+       "friday": "Kurudu",
+       "saturday": "Kukuak",
+       "sun": "Tiw",
+       "mon": "Ton",
+       "tue": "Mir",
+       "wed": "Mad",
+       "thu": "Tad",
+       "fri": "Kur",
+       "sat": "Kuk",
+       "january": "Milatok",
+       "february": "Mansak",
+       "march": "Gamot",
+       "april": "Ngiop",
+       "may_long": "Mikat",
+       "june": "Mahas",
+       "july": "Madas",
+       "august": "Magus",
+       "september": "Manom",
+       "october": "Gumas",
+       "november": "Milau",
+       "december": "Momuhau",
        "january-gen": "Milatok",
        "february-gen": "Mansak",
        "march-gen": "Gomot",
index 9ea6ec5..28fee08 100644 (file)
@@ -37,7 +37,7 @@
        "tog-shownumberswatching": "निगरानी गरिरहेका प्रयोगकर्ताहरूको संख्या धेखाउन्या",
        "tog-oldsig": "तमरो अहिलको हस्ताक्षर:",
        "tog-fancysig": "मेरा दस्तखतलाई विकि पाठको रुपमी लिने (स्वत लिङ्क बिना)",
-       "tog-uselivepreview": "पà¥\8dरतà¥\8dयà¤\95à¥\8dष à¤ªà¥\88लà¥\8dलà¥\80à¤\95à¥\8bरà¥\81प à¤ªà¥\8dरयà¥\8bà¤\97 à¤\97र",
+       "tog-uselivepreview": "पà¥\83षà¥\8dठ à¤ªà¥\81नरà¥\8dभरण à¤¨à¤\85रà¥\87à¤\87 à¤ªà¥\82रà¥\8dवावलà¥\8bà¤\95न à¤§à¥\87à¤\95ाà¤\83",
        "tog-forceeditsummary": "खाली सम्पादन शीर्षक प्रविष्टि गरेपछा मलाई सोधन्या",
        "tog-watchlisthideown": "मेरा सम्पादनहरू निगनारी सूचीबठेई लुकाऊन्या",
        "tog-watchlisthidebots": "बोट सम्पादनहरू ध्यान सूचीबठेई लुकाउन्या",
@@ -53,6 +53,7 @@
        "tog-norollbackdiff": "पैलास्थितिमी फर्काएपछा भिन्नता हटाउन्या",
        "tog-useeditwarning": "सम्पादनहरू सङ्ग्रह नगरिएका अवस्थामी अर्को पानामी जान खोज्या चेतावनी धेखाउन्या",
        "tog-prefershttps": "प्रवेश गरन्ज्या जबलै सुरक्षित जडानको प्रयोग गर्न्या",
+       "tog-requireemail": "पासवर्ड पुनःचयन खिलाइ इमेल चायीन्छ",
        "underline-always": "जबलै",
        "underline-never": "कभैई नाई",
        "underline-default": "खोल और ब्राउजर निर्धारित",
        "index-category": "क्रमाङ्कित पानाहरू",
        "noindex-category": "अनुक्रमित नअरियाऽ पन्नाअन",
        "broken-file-category": "टुटेको फाइल लिङ्कहरूसितको पाना",
+       "categoryviewer-pagedlinks": "($1) ($2)",
+       "category-header-numerals": "$1–$2",
        "about": "बारेमी",
        "article": "सामाग्री पानो",
        "newwindow": "(नौलो विन्डोमी खुलन्छ)",
        "returnto": "$1 मी फर्क।",
        "tagline": "{{SITENAME}} बठेइ",
        "help": "मद्दत",
+       "help-mediawiki": "मिडियाविकि का बारेमी मद्दत",
        "search": "खोजी",
        "search-ignored-headings": " #<!-- leave this line exactly as it is --> <pre>\n# Headings that will be ignored by search.\n# Changes to this take effect as soon as the page with the heading is indexed.\n# You can force page reindexing by doing a null edit.\n# The syntax is as follows:\n#   * Everything from a \"#\" character to the end of the line is a comment.\n#   * Every non-blank line is the exact title to ignore, case and everything.\nReferences\nExternal links\nSee also\n #</pre> <!-- leave this line exactly as it is -->",
        "searchbutton": "खोज:",
        "redirectto": "पठाएको पाना:",
        "lastmodifiedat": "यै पन्नालाई छाड्डीबार $1मी $2 बजे सम्पादन गरियाऽ थ्यो।",
        "viewcount": "यो पाना हेरियाको थियो {{PLURAL:$1|एकपटक|$1 पटक}}",
-       "protectedpage": "सà¥\81रà¤\95à¥\8dषित à¤\97रà¥\8dयाà¤\95ा à¤ªà¤¾à¤¨à¤¾à¤¹à¤°à¥\82",
+       "protectedpage": "सà¥\81रà¤\95à¥\8dषित à¤\97रियाà¤\95ा à¤ªà¤¨à¥\8dनाà¤\85न",
        "jumpto": "यैमी फट्टाक:",
        "jumptonavigation": "भ्रमण गरऽ",
        "jumptosearch": "खोजऽ",
        "view-pool-error": "माफ गर्या , अहिल सर्भरहरूमी कामको भार भौत रह्या छ।\nभौत भौत प्रयोगकर्ताहरू यै पाना हेद्या प्रयास गरी रह्या छन्।\nकृपया यो पाना पुन: हेर्नु अगाडि थोक्कै पख ।\n\n$1",
        "generic-pool-error": "माफ गर्या , अहिल सर्भरहरूमी कामको भार भौत रह्या छ।\nभौत भौत प्रयोगकर्ताहरू यै पाना हेद्या प्रयास गरी रह्या छन् ।\nकृपया यो पाना पुन: हेर्नु अगाडि थोक्कै पख ।",
-       "pool-timeout": "समय à¤¸à¤\95ियà¥\8b à¤¬à¤¨à¥\8dद à¤\97रà¥\8dनà¥\87 à¤ªà¥\8dरतà¥\80à¤\95à¥\8dषामी",
-       "pool-queuefull": "पà¥\8dरतà¥\80क्षा पङ्क्ति भरियो",
+       "pool-timeout": "बनà¥\8dद à¤\97दà¥\8dदाà¤\87 à¤¸à¤®à¤¯à¤¸à¥\80मा à¤¸à¤\95à¥\80नà¥\8dया à¤ªà¥\8dरतिà¤\95à¥\8dषा मी",
+       "pool-queuefull": "पà¥\8dरतिक्षा पङ्क्ति भरियो",
        "pool-errorunknown": "अज्ञात गल्ती",
        "pool-servererror": "पुल काउन्टर सेवा उपलब्ध नाइथिन् ($1)।",
        "poolcounter-usage-error": "प्रयोग गल्ती:$1",
        "versionrequired": "MediaWiki संस्करण $1 चाईन्या",
        "versionrequiredtext": "ये पाना प्रयोग गर्नका लागि MediaWiki $1 संस्करण चाहिन्छ ।\nहेर  [[Special:Version|version page]]",
        "ok": "भयो",
+       "pagetitle": "$1 - {{SITENAME}}",
+       "pagetitle-view-mainpage": "{{SITENAME}}",
+       "backlinksubtitle": "← $1",
        "retrievedfrom": " \"$1\" बठे निकालियाऽ",
        "youhavenewmessages": "{{PLURAL:$3|तम सित छन}} $1 ($2)।",
        "youhavenewmessagesfromusers": "{{PLURAL:$3|अर्खा प्रयोगकर्ता|$3 प्रयोगकर्ताअन}} ($2) मी है {{PLURAL:$4|तम सित}} $1 छन।",
        "site-atom-feed": "$1 एटम फीड",
        "page-rss-feed": "\"$1\" आरएसएस फिड",
        "page-atom-feed": "\"$1\" एटम फिड",
+       "feed-rss": "आरएसएस",
        "red-link-title": "$1 (पन्ना उपलब्ध नाइँथिन)",
        "sort-descending": "अवरोहण क्रममी मिलाउन्या",
        "sort-ascending": "आरोहण क्रममी मिलाउन्या",
        "badarticleerror": "यो कार्य यै पनामी गर्न नाईंमिल्लो।",
        "cannotdelete": "\"$1\" पाना वा फाइल मेट्ट सकिएन।\nयो पैल्लीबठे मेटियाको हुनु पडन्छ।",
        "cannotdelete-title": "पाना  \"$1\" लाई मेट्टू सकिएन",
+       "delete-scheduled": "$1 पन्ना मेटौनाइ खिलाइ समय निर्धारित अरीरैछ।\nकृपया धीरज राखः।",
        "delete-hook-aborted": "हुकले सम्पादनकार्य बन्द गरिदियो ।\nकोइ कारण दिइएन ।",
        "no-null-revision": "$1 पाना लागि खालि पुनरावलोकन सिर्जना गर्न सकिएन",
        "badtitle": "गलत शीर्षक",
        "ns-specialprotected": "विशेष पृष्ठहरू सम्पादन अद्दु नाइँ सकिनो।",
        "titleprotected": "[[User:$1|$1]]द्वारा ये शीर्षक निर्माणहुनबठे जोगाइया छ।\nकारण <em>$2</em> हो ।",
        "filereadonlyerror": "\"$1\" फाइललाई परिवर्तन अद्दु नाइँ सकिनो क्याईकि फाइल भण्डार \"$2\" केवल पड्ड्या स्थिति (read-only mode)मी छ।\n\nयेलाई सुरक्षित अद्द्या प्रवन्धकले यो कारण दीराइछ: ''$3''।",
+       "invalidtitle": "अमान्य शीर्षक",
        "invalidtitle-knownnamespace": "\"$2\" नाउँबार रे \"$3\" पाठ भया: अमान्य शीर्षक",
        "invalidtitle-unknownnamespace": "अपछ्याणो नाउँबार अङ्क $1 रे पाठ \"$2\" भया: अमान्य शीर्षक",
        "exception-nologin": "प्रवेश (लग ईन) नगरिएको",
        "virus-scanfailed": "जँचाई असफल(कोड $1)",
        "virus-unknownscanner": "थानभया एन्टीभाइरस:",
        "logouttext": "<strong>तमी अहिल बाहिर निस्क्याका  छौ।</strong>\n\nयाद राख्या तमीले ब्राउजरको क्याच खालि नगर्यासम्म कुनै पानाहरूमी तमी अझैं प्रवेश गरिरख्याको धेकाउन सक्छ।",
+       "logging-out-notify": "तम लगआउट हुन्नाछः, पख्याः हाँ।",
+       "logout-failed": "अइल लगआउट नाइहोइसकियो: $1",
        "cannotlogoutnow-title": "अईल भाईर निकल्ल नाइँ पाईनो",
        "cannotlogoutnow-text": "भाईर निकल्ल असंभव छ जब प्रयोग $1",
        "welcomeuser": "$1स्वागत छ!",
        "mailmypassword": "पासवर्ड पूर्वनिर्धारित गर",
        "passwordremindertitle": "{{SITENAME}}का लागि नयाँ अस्थायी पासवर्ड",
        "passwordremindertext": "कसैले (सायद तमी, IP ठेगाना $1 बाट), {{SITENAME}}($4) को लागि नौलो पासवर्ड अनुरोध गर्या छ । प्रयोगकर्ता \"$2\" को लागि नौलो अस्थायी पासवर्ड \"$3\"तयार पारिया छ । यदि यो तमरो इच्छामी भयाको भया अहिले तमीले लगइन गरीबर नौलो पासवर्ड छान्नु पड्ड्या हुन्छ ।\nतमरो अस्थायी पासवर्ड  {{PLURAL:$5|एक दिन|$5 दिनहरू पछि}} अमान्य हुन्याछ ।\n\nयदि कोही अरुले नै अनुरोध गर्याको हो भण्या , या तमीले आफ्नो पासवर्ड सम्झ्यौ भण्या, अथवा\nत्यैलाई परिवर्तन गर्न चाहन्नौ भण्या, तमीले यो सन्देसको वेवास्ता गद्दसक्द्याहौ र पुरानै पासवर्ड प्रयोग गरिरहन सक्द्याहौ ।",
+       "noemailcreate": "तम ले मान्य इमेल ठिगाना दिन आवश्यक छ।",
        "blocked-mailpassword": "तमरा IP ठेगानालाई सम्पादन गद्द बठे रोक लाइराइछ। दुरुपयोग रोक्दाइ, तमरा IP ठेगाना बठेइ प्रवेसशब्द पुनर्लाभ प्रक्रिया प्रयोग अद्द्या अनुमति आथिन।",
        "mailerror": " चिठी :$1 पठाउँदा गल्ती भयो",
        "noemailprefs": "निम्न सुविधाहरू राम्डरी काम गद्दको लागि तमरो रोजाईमी आफ्नो ई-मेल ठेगाना खुलाओ ।",
        "anoneditwarning": "<strong>चेतावनी:</strong> तमले प्रवेश अरेको नाइथिन । तमरो आइपि ठेगाना पाना सम्पादन इतिहासमि दर्ता गरिन्या छ र यो सब्बैले हेद्द सक्कान । यदि तमलाईँ <strong>[$1 लगईन]</strong> वा <strong>[$2 नयाँ खाता बनाउन्या] गर्याभण्या तमबठे गरियाको सम्पादन तमरो प्रयोगकर्तानाममि जोडिन्याछ ।",
        "missingsummary": "'''यादगर्या :''' तमीले सम्पादन सारांश दियाका छैनौ ।\nयदि तमीले \"$1\"  थिच्यौ भण्या , सारांश बिना नै सङ्ग्रहित गरिन्या छ ।",
        "selfredirect": "<strong>चेतावनी:</strong> तम यै पानालाई आफुमी पुनः निर्देशित गद्द लाग्याछौ ।\nहुनसक्छ तम अनुप्रेषितको लागि गलत लक्ष्य निर्दिष्ट गद्द लाग्याछौ, वा गलत पानाको सम्पादन गद्द लाग्याछौ ।\nतम पुनः एकपल्ट \"$1\" क्लिक गद्दाछौ, पुनः निर्देशित तसै लै बनाइन्याछ।",
-       "missingcommenttext": "à¤\95à¥\83पया à¤¤à¤²à¤¤à¤¿à¤° à¤\9fिपà¥\8dपणà¥\80 à¤°à¤¾à¤\96 ।",
+       "missingcommenttext": "à¤\95à¥\83पया à¤\9fिपà¥\8dपणà¥\80 à¤°à¤¾à¤\96à¤\83।",
        "missingcommentheader": "'''याद गर :''' तमले टिप्पणीमी विषय /शीर्ष पंक्ति  दियाका छैनौ ।\nतमले फेरि \"$1\"  थिच्यौ भण्या , तमरो सम्पादन यसै रुपमी संग्रहित हुन्याछ ।",
        "summary-preview": "सम्पादन सारांशोः पूर्वालोकन:",
        "subject-preview": "विषयोः पूर्वरुप:",
        "page_first": "पैल्लो",
        "page_last": "छाड्डीबारको",
        "histlegend": "अन्तर चयन:संशोधनहरूको तुलनाको लागि रेडियो बाकसमी क्लिक गरिबर इण्टर गर अथवा तल दियाको बटनमी थिच <br />\nलिजेंड: (चालू): '''({{int:cur}})''' = अवतरणको बीचमी अन्तर, '''({{int:last}})''' = पैल्लीका अवतरणको बीचमी अन्तर, '''{{int:minoreditletter}}''' = नानो परिवर्तन।",
-       "history-fieldset-title": "सà¤\82शà¥\8bधनà¤\85न à¤\96िलाà¤\87 à¤\96à¥\8bà¤\9cऽ",
+       "history-fieldset-title": "सà¤\82शà¥\8bधनà¤\85न à¤\9bानà¤\83",
        "history-show-deleted": "संशोधन मेटियाको मात्तरै",
        "histfirst": "सबहै पुरानो",
        "histlast": "नयाँ",
        "historysize": "({{PLURAL:$1|१ अक्षर|$1 अक्षरहरू}})",
-       "historyempty": "(खाली)",
+       "historyempty": "खालि",
        "history-feed-title": "पुनरावलोकन इतिहास",
        "history-feed-description": "विकीमा यो पानको पुनरावलोकन इतिहास",
        "history-feed-item-nocomment": "$1  $2मी",
        "rev-deleted-user": "(प्रयोगकर्ता नाम हटाइयो)",
        "rev-deleted-event": "(लग विवरण हटाइयो)",
        "rev-suppressed-text-unhide": "यै पानाको पुनरावलोकन '''दमन''' गरियाको छ ।\nविस्तृत जानकारी [{{fullurl:{{#Special:Log}}/delete|पानो={{FULLPAGENAMEE}}}} दमन लग] पाउन सकिन्छ ।\nयदि तम अगाडि बढ्ड चाहन्छौ भण्या पनि तमीले  [$1 यि संशोधनहरू हेद्द] पाउन्या हौ ।",
-       "rev-delundel": "दधà¥\87à¤\96ाà¤\89नà¥\87/लà¥\81à¤\95ाà¤\89नà¥\8dया",
+       "rev-delundel": "दà¥\83शà¥\8dयता à¤¬à¤¦à¥\87लà¤\83",
        "rev-showdeleted": "धेकाउन्या",
        "revisiondelete": "पुनरावलोकनअन मेट्याऽ/मेट्याऽ रद्द अद्द्या",
        "revdelete-nooldid-title": "अमान्य पुनरावलोकन लक्ष",
        "prefs-editwatchlist-clear": "तमरो अवलोकनसूची मेटा",
        "prefs-watchlist-days": "ध्यान सूचीमी धेकाउने दिनहरू:",
        "prefs-watchlist-days-max": "बर्ती है बर्ती $1 {{PLURAL:$1|दिन|दिनअन}}",
-       "prefs-watchlist-edits": "à¤\89à¤\9aà¥\8dà¤\9aतम à¤ªà¤°à¤¿à¤µà¤°à¥\8dतन à¤¸à¤\82à¤\96à¥\8dया à¤¬à¤¢à¤¾à¤\87à¤\8fà¤\95à¥\8b à¤¨à¤¿à¤\97रानà¥\80 à¤¸à¥\82à¤\9aà¥\80मà¥\80  à¤§à¤\95ाà¤\89नà¤\95ा à¤²à¤¾à¤\97ि :",
+       "prefs-watchlist-edits": "à¤\85वलà¥\8bà¤\95नसà¥\82à¤\9aà¥\80 à¤®à¥\80 à¤§à¥\87à¤\95à¥\8cना à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनà¤\85न à¤\95à¥\8b à¤\89à¤\9aà¥\8dà¤\9aतम à¤¸à¤\82à¤\96à¥\8dया:",
        "prefs-watchlist-edits-max": "सबै है ज्यादा संख्या : १०००",
        "prefs-watchlist-token": "अवलोकन सूची टोकन:",
        "prefs-misc": "साधारण",
        "timezoneregion-europe": "युरोप",
        "timezoneregion-indian": "हिन्द महासागर",
        "timezoneregion-pacific": "प्राशान्त महासागर",
-       "allowemail": "à¤\94र à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dताबठà¥\87 à¤ªà¥\8cनà¥\8dया à¤\88मà¥\87ल à¤¸à¤\95à¥\8dषम à¤\97र।",
+       "allowemail": "à¤\94र à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dताà¤\85न à¤²à¤¾à¤\87 à¤®à¥\81à¤\87 à¤²à¤¾à¤\87 à¤\88मà¥\87ल à¤ªà¤ à¥\8cनà¥\87à¤\87 à¤\85नà¥\81मति à¤¦à¤¿à¤¯",
        "prefs-searchoptions": "खोज",
        "prefs-namespaces": "नामठौर:",
        "default": "पूर्वनिर्धारित",
        "prefs-files": "फाइलहरू",
        "prefs-custom-css": "अनुकुलित CSS",
        "prefs-custom-js": "अनुकुल जाभास्क्रिप्ट",
-       "prefs-common-config": "साà¤\9dा CSS/à¤\9cाभा à¤¸à¥\8dà¤\95à¥\8dरिपà¥\8dà¤\9f à¤¸à¤¬à¥\88 à¤\95ि à¤²à¥\87à¤\96ा:",
+       "prefs-common-config": "सबà¥\88 à¤\96à¥\8bलà¤\85न à¤\96िलाà¤\87 à¤¸à¤¾à¤\9dा à¤¸à¥\80à¤\8fसà¤\8fस/à¤\9cà¥\87सन/à¤\9cावासà¥\8dà¤\95à¥\8dरिपà¥\8dà¤\9f:",
        "prefs-reset-intro": "तम ये पृष्ठलाई आफनो अभिरुचीहरू साइट पूर्वावस्थामी फर्काउनत फर्काउन प्रयोग गद्दु सकन्छौ । तै पाछा ये लाई रद्द गद्दु सकन्छौ ।",
        "prefs-emailconfirm-label": "इ-मेल एकिन प्रक्रिया:",
        "youremail": "ईमेल",
        "grouppage-bureaucrat": "{{ns:project}}:प्रशासकअन",
        "grouppage-suppress": "{{ns:project}}:लुकौन्या",
        "right-read": "पृष्ठहरू पढ",
-       "right-edit": "पà¥\83षà¥\8dठहरà¥\82 à¤¸à¤®à¥\8dपादन à¤\97र",
+       "right-edit": "पनà¥\8dनाà¤\85न à¤¸à¤®à¥\8dपादन à¤\97रà¤\83",
        "right-createpage": "पृष्ठ निर्माण गर(छलफल पृष्ठहरू बाहेक)",
        "right-createtalk": "छलफल पृष्ठ सृजना गर",
        "right-createaccount": "नयाँ प्रयोगकर्ता खाता सृजना गर।",
        "right-reupload-own": "आफैले अपलोड  गरया रई आया फाइल अधिलेखन गर्न्या",
        "right-reupload-shared": "साझा मिडिया भण्डारमी स्थानियरुपमी फाइलहरू अधिक्रमण गर्न्या",
        "right-upload_by_url": "URL बठे फाइल उर्ध्वभरण गर्ने",
-       "right-purge": "साà¤\87à¤\9fà¤\95à¥\8b à¤\95à¥\8dयाश( cache) à¤¨à¤¿à¤¶à¥\8dà¤\9aित à¤¨à¤\97रिà¤\95नà¥\88 à¤ªà¤°à¥\8dà¤\9c(Purge) à¤\97रà¥\8dनà¥\87",
+       "right-purge": "यà¥\87à¤\87 à¤ªà¤¨à¥\8dना à¤\95à¥\8b à¤¸à¤¾à¤\87à¤\9f à¤\95à¥\8dयाश(cache) à¤ªà¤°à¥\8dà¤\9c(Purge) à¤\97रà¤\83",
        "right-writeapi": "लेखन API प्रयोग गद्य्या",
        "right-delete": "पृष्ठहरू मेट्ने",
        "right-bigdelete": "लामो इतिहास भयाका पानाहरू मेट्ट्या",
        "right-userrights-interwiki": "अन्य विकिहरूमी प्रयोगकर्ताहरूको अधिकार सम्पादन गद्या",
        "right-override-export-depth": "गहिराइ ५ सम्म लिंक गरियाका पानाहरू सहित निर्यात गद्या",
        "right-sendemail": "अन्य प्रयोगकर्तानलाई इमेल पठाउन्या",
-       "grant-editmycssjs": "तमरो प्रयोगकर्ता CSS/JavaScript सम्पादन गरऽ",
-       "grant-editmyoptions": "तमरा à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤\85भिरà¥\81à¤\9aà¥\80à¤\87नलाà¤\88 à¤¸à¤®à¥\8dपादन à¤\97रऽ",
+       "grant-editmycssjs": "तमरो प्रयोगकर्ता CSS/JSON/JavaScript सम्पादन गरः",
+       "grant-editmyoptions": "तमरा à¤ªà¥\8dरयà¥\8bà¤\97à¤\95रà¥\8dता à¤\85भिरà¥\81à¤\9aिà¤\87न à¤°à¥\87 à¤\9cà¥\87सन(JSON) à¤®à¤¿à¤²à¤¾à¤¨ à¤¸à¤®à¥\8dपादन à¤\97रà¤\83",
        "grant-editmywatchlist": "तमरो अवलोकनसूची सम्पादन गर",
        "grant-editpage": "भैरया पृष्ठहरू सम्पादन गर",
        "grant-editprotected": "सुरक्षित पृष्ठ सम्पादन",
        "recentchanges-legend-heading": "<strong>आदर्श वाक्य:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|नौला पानाको सूची]] यैलाई लै हेरिदिय)",
        "rcfilters-savedqueries-rename": "पुनर्नामकरण",
-       "rcfilters-savedqueries-remove": "हà¤\9fाऽ",
+       "rcfilters-savedqueries-remove": "मà¥\87à¤\9fà¤\83",
        "rcfilters-savedqueries-new-name-label": "नाउँ",
        "rcfilters-savedqueries-cancel-label": "रद्द",
        "rcfilters-filter-editsbyself-label": "तम हताँ अरियाऽ फेरबदेलाअन",
        "rcfilters-filter-editsbyother-label": "अउर हताँ अरियाऽ फेरबदेलाअन",
        "rcfilters-filter-editsbyother-description": "तमरा आफ्फुनाइ बाहेक अउर सप्पै फेरबदेलाअन।",
        "rcfilters-filtergroup-lastrevision": "छाड्डीबारोः संशोधन",
-       "rcfilters-filter-lastrevision-label": "à¤\9bाडà¥\8dडà¥\80बारà¥\8bà¤\83 संशोधन",
+       "rcfilters-filter-lastrevision-label": "सबहà¥\88 à¤¨à¥\8cलà¥\8b संशोधन",
        "rclistfrom": "$3 $2 देखिका नयाँ परिवर्तनहरू देखाउन्या",
        "rcshowhideminor": "$1 सानतिनो सम्पादन",
        "rcshowhideminor-show": "धेकाइदिय",
        "filehist-comment": "टिप्पणी",
        "imagelinks": "फाइल उपयोग",
        "linkstoimage": "यै चित्रमी निम्न{{PLURAL:$1|पाना जोडिनान{{PLURAL:$1|}}|$1 पानाहरू जोडिनान्}}:",
-       "nolinkstoimage": "यà¥\8b à¤\9aितà¥\8dरसित à¤²à¤¿à¤\82à¤\95भयाà¤\95ि à¤\95à¥\8bà¤\87 à¤ªà¤¾à¤¨à¤¾ à¤¨à¤¾à¤\87थà¥\80",
+       "nolinkstoimage": "यà¥\87à¤\87 à¤«à¤¾à¤\87ल à¤ªà¥\8dरयà¥\8bà¤\97 à¤­à¤¯à¤¾à¤\83 à¤\95à¥\8bà¤\87 à¤²à¥\88 à¤ªà¤¨à¥\8dना à¤¨à¤¾à¤\87थिन।",
        "morelinkstoimage": "यै फाइलको [[Special:WhatLinksHere/$1|थप लिंकहरू]] हेर ।",
        "sharedupload-desc-here": "यो फाइल $1 बठे हो र और  परियोजनाहरू बठे पन प्रयोग गद्द सकिन्याछ । \nताखाइ यैको [$2 फ़ाइल विवरण पानो]मि रयाका विवरण तल्तिर दियाको छ।",
        "filepage-nofile": "येइ नाउँ को कोइ लै फाइल नाइथिन।",
        "tooltip-rollback": "\"पूर्वरुप\" ले यो पानाक्क सम्पादन(हरू) खारेज अरिबरे पानालाई एक क्लिकमि पाछाडीको सम्पादनमि पुगाइदिन्छ ।",
        "tooltip-undo": "\"रद्द\"ले पछिल्लो सम्पादन खारेज गरिबरे पूर्वावलोकनमा धेकाउछ ।\nयैले सारांशमा कारण राख्ख दिन्याछ।",
        "tooltip-summary": "नानो सारांश हालिदिय",
-       "siteusers": "{{SITENAME}} {{PLURAL:$2|प्रयोगकर्ता|प्रयोगकर्ताहरू}} $1",
+       "siteusers": "{{SITENAME}} {{PLURAL:$2|{{GENDER:$1|प्रयोगकर्ता}}|प्रयोगकर्ताअन}} $1",
        "anonusers": "{{SITENAME}} का नाम नभयाका {{PLURAL:$2| प्रयोगकर्ता|प्रयोगकर्ताहरू}} $1",
        "simpleantispam-label": "ऐन्टी-स्प्याम जाँच।\nयैलाई <strong>नाइँ</strong> भद्य्या!",
        "pageinfo-title": "\"$1\" खिलाइ जानकारी",
        "imgmultipagenext": "अर्खो पन्ना →",
        "imgmultigo": "जाऽ!",
        "imgmultigoto": "$1 पन्ना मैं जाऽ",
-       "size-bytes": "$1 अक्षरहरू",
+       "size-bytes": "$1 {{PLURAL:$1|बाइट|बाइटअन}}",
        "size-kilobytes": "$1 किलोबाइट",
        "size-megabytes": "$1 मेगाबाइट",
        "size-gigabytes": "$1 गिगाबाइट",
index f6ea46c..82826c5 100644 (file)
@@ -47,6 +47,7 @@
        "tog-useeditwarning": "Warn me when I leave an edit page with unsaved changes",
        "tog-prefershttps": "Always use a secure connection while logged in",
        "tog-showrollbackconfirmation": "Show a confirmation prompt when clicking on a rollback link",
+       "tog-requireemail": "Require email for password resets",
        "underline-always": "Always",
        "underline-never": "Never",
        "underline-default": "Skin or browser default",
        "prefs-help-email": "Email address is optional, but is needed for password resets, should you forget your password.",
        "prefs-help-email-others": "You can also choose to let others contact you by email through a link on your user or talk page.\nYour email address is not revealed when other users contact you.",
        "prefs-help-email-required": "Email address is required.",
+       "prefs-help-requireemail": "If checked, will only send password reset emails if the resetting person has provided both username and email for this account.",
        "prefs-info": "Basic information",
        "prefs-i18n": "Internationalisation",
        "prefs-signature": "Signature",
        "ipblocklist-legend": "Find a blocked user",
        "blocklist-userblocks": "Hide account blocks",
        "blocklist-tempblocks": "Hide temporary blocks",
+       "blocklist-indefblocks": "Hide indefinite blocks",
        "blocklist-addressblocks": "Hide single IP blocks",
        "blocklist-type": "Type:",
        "blocklist-type-opt-all": "All",
index 96cc2a4..9c83390 100644 (file)
        "exif-photometricinterpretation-8": "CIE L*a*b*",
        "exif-photometricinterpretation-9": "CIE L*a*b* (pengkodean ICC)",
        "exif-photometricinterpretation-10": "CIE L*a*b* (pengkodean ITU)",
+       "exif-photometricinterpretation-32803": "Aturan Filter Warna",
+       "exif-photometricinterpretation-34892": "Linear raw",
        "exif-unknowndate": "Tanggal tak diketahui",
        "exif-orientation-1": "Normal",
        "exif-orientation-2": "Dibalik horisontal",
        "exif-scenetype-1": "Gambar foto langsung",
        "exif-customrendered-0": "Proses normal",
        "exif-customrendered-1": "Proses kustom",
+       "exif-customrendered-2": "HDR (aslinya tidak disimpan)",
+       "exif-customrendered-3": "HDR (aslinya disimpan)",
+       "exif-customrendered-4": "Asli (untuk HDR)",
+       "exif-customrendered-6": "Panorama",
+       "exif-customrendered-7": "Portret HDR",
+       "exif-customrendered-8": "Potret",
        "exif-exposuremode-0": "Pajanan otomatis",
        "exif-exposuremode-1": "Pajanan manual",
        "exif-exposuremode-2": "Braket otomatis",
index d2c74f5..ae53416 100644 (file)
        "exif-scenetype-1": "Direktefotografert bilde",
        "exif-customrendered-0": "Normal prosess",
        "exif-customrendered-1": "Tilpasset prosess",
+       "exif-customrendered-2": "HDR (ingen original lagret)",
+       "exif-customrendered-3": "HDR (original lagret)",
+       "exif-customrendered-4": "Original (for HDR)",
+       "exif-customrendered-6": "Panorama",
+       "exif-customrendered-7": "Portrett-HDR",
+       "exif-customrendered-8": "Portrett",
        "exif-exposuremode-0": "Automatisk eksponering",
        "exif-exposuremode-1": "Manuell eksponering",
        "exif-exposuremode-2": "Automatisk alternativeksponering",
index f8709f3..64725b4 100644 (file)
@@ -6,7 +6,8 @@
                        "Matma Rex",
                        "Sp5uhe",
                        "Stlmch",
-                       "Railfail536"
+                       "Railfail536",
+                       "Rail"
                ]
        },
        "exif-imagewidth": "Szerokość",
index bd46ad5..5f82f91 100644 (file)
        "exif-gpsmeasuremode-2": "2-رخي ماپ",
        "exif-gpsmeasuremode-3": "3-رخي ماپ",
        "exif-gpsspeed-k": "ڪلوميٽر في ڪلاڪ",
-       "exif-gpsspeed-m": "ميل في ڪلاڪ",
+       "exif-gpsspeed-m": "ميلَ في ڪلاڪ",
        "exif-gpsspeed-n": "ناٽس",
        "exif-gpsdestdistance-k": "ڪلميٽر",
-       "exif-gpsdestdistance-m": "ميل",
-       "exif-gpsdestdistance-n": "سامونڊي ميل",
+       "exif-gpsdestdistance-m": "ميلَ",
+       "exif-gpsdestdistance-n": "سامونڊي ميلَ",
        "exif-objectcycle-p": "رڳو شام",
        "exif-dc-contributor": "ڀاڱيدار",
        "exif-dc-date": "تاريخون",
index 994b1e1..2869768 100644 (file)
        "logentry-partialblock-block-page": "{{PLURAL:$1|sivua|sivuja}} $2",
        "logentry-partialblock-block-ns": "{{PLURAL:$1|nimiavaruutta|nimiavaruuksia}} $2",
        "logentry-partialblock-block": "$1 {{GENDER:$2|esti}} käyttäjää {{GENDER:$4|$3}} muokkaamasta $7. Eston kesto on $5 $6",
-       "logentry-partialblock-reblock": "$1 {{GENDER:$2|muutti}} käyttäjän {{GENDER:$4|$3}} muokkauseston asetuksia estäen muokkausten tekemisen $7. Eston kesto on $5 $6",
+       "logentry-partialblock-reblock": "$1 {{GENDER:$2|muutti}} käyttäjän {{GENDER:$4|$3}} muokkauseston asetuksia niin, että hän ei voi muokata $7. Eston kesto on $5 $6",
        "logentry-non-editing-block-block": "$1 {{GENDER:$2|esti}} käyttäjää {{GENDER:$4|$3}} suorittamasta määrättyjä toimenpiteitä (lukuun ottamatta muokkaamista). Eston kesto on $5 $6",
        "logentry-non-editing-block-reblock": "$1 {{GENDER:$2|muutti}} käyttäjän {{GENDER:$4|$3}} toimintaeston asetuksia, jotka koskevat määrättyjä toimenpiteitä. Eston kesto on $5 $6",
        "logentry-suppress-block": "$1 {{GENDER:$2|esti}} käyttäjän {{GENDER:$4|$3}}. Eston kesto on $5 $6",
index f2fbb2d..2e6ccf1 100644 (file)
        "tog-useeditwarning": "M’avertir quand je quitte une page en cours de modification sans avoir sauvegardé",
        "tog-prefershttps": "Toujours utiliser une connexion sécurisée lorsque je suis connecté",
        "tog-showrollbackconfirmation": "Afficher une demande de confirmation en cliquant sur un lien d’annulation",
+       "tog-requireemail": "Nécessiter un courriel pour les réinitialisations de mot de passe",
        "underline-always": "Toujours",
        "underline-never": "Jamais",
        "underline-default": "Valeur par défaut du thème ou du navigateur",
        "filerenameerror": "Impossible de renommer le fichier « $1 » en « $2 ».",
        "filedeleteerror": "Impossible de supprimer le fichier « $1 ».",
        "directorycreateerror": "Impossible de créer le répertoire « $1 ».",
-       "directoryreadonlyerror": "Le répertoire « $1 » est en lecture seule.",
-       "directorynotreadableerror": "Le répertoire « $1 » n’est pas lisible.",
+       "directoryreadonlyerror": "Le répertoire « $1 » est en lecture seule.",
+       "directorynotreadableerror": "Le répertoire « $1 » n’est pas lisible.",
        "filenotfound": "Impossible de trouver le fichier « $1 ».",
        "unexpected": "Valeur inattendue : « $1 » = « $2 ».",
        "formerror": "Erreur : impossible de soumettre le formulaire.",
        "badarticleerror": "Cette action ne peut pas être effectuée sur cette page.",
        "cannotdelete": "Impossible de supprimer la page ou le fichier « $1 ».\nLa suppression a peut-être déjà été effectuée par quelqu’un d’autre.",
        "cannotdelete-title": "Impossible de supprimer la page « $1 »",
-       "delete-scheduled": "La page « $1 » est programmée pour être supprimée.\nVeuillez patienter.",
+       "delete-scheduled": "La page « $1 » est programmée pour être supprimée.\nVeuillez patienter.",
        "delete-hook-aborted": "Suppression annulée par une extension.\nAucune explication n’a été fournie.",
-       "no-null-revision": "Impossible de créer une nouvelle révision vide pour la page « $1 »",
+       "no-null-revision": "Impossible de créer une nouvelle révision vide pour la page « $1 »",
        "badtitle": "Mauvais titre",
        "badtitletext": "Le titre de la page demandée est non valide, vide, ou mal formé s’il s’agit d’un titre inter-langue ou inter-projet.\nIl contient peut-être un ou plusieurs caractères qui ne peuvent pas être utilisés dans les titres.",
        "title-invalid-empty": "Le titre de la page demandée est vide ou contient seulement le nom d’un espace de noms.",
        "virus-scanfailed": "échec de l’analyse (code $1)",
        "virus-unknownscanner": "antivirus inconnu :",
        "logouttext": "<strong>Vous êtes à présent déconnecté{{GENDER:||e|(e)}}.</strong>\n\nNotez que certaines pages peuvent être encore affichées comme si vous étiez toujours connecté, jusqu’à ce que vous effaciez le cache de votre navigateur.",
-       "logging-out-notify": "Vous allez être déconnecté, veuillez attendre.",
-       "logout-failed": "Impossible de se déconnecter maintenant : $1",
+       "logging-out-notify": "Vous allez être déconnecté, veuillez patienter.",
+       "logout-failed": "Impossible de se déconnecter maintenant: $1",
        "cannotlogoutnow-title": "Impossible de se déconnecter maintenant",
        "cannotlogoutnow-text": "La déconnexion n’est pas possible en utilisant $1.",
        "welcomeuser": "Bienvenue, $1 !",
        "noname": "Vous n’avez pas saisi un nom d’utilisateur valide.",
        "loginsuccesstitle": "Connecté",
        "loginsuccess": "<strong>Vous êtes maintenant connecté{{GENDER:$1||e|(e)}} à {{SITENAME}} en tant que « $1 ».</strong>",
-       "nosuchuser": "L’utilisateur « $1 » n’existe pas.\nLes noms d’utilisateur sont sensibles à la casse.\nVérifiez l’orthographe, ou [[Special:CreateAccount|créez un nouveau compte]].",
+       "nosuchuser": "L’utilisateur « $1 » n’existe pas.\nLes noms d’utilisateur sont sensibles à la casse.\nVérifiez l’orthographe ou [[Special:CreateAccount|créez un nouveau compte]].",
        "nosuchusershort": "Il n’y a pas de contributeur avec le nom « $1 ».\nVeuillez vérifier l’orthographe.",
        "nouserspecified": "Vous devez saisir un nom d’utilisateur.",
        "login-userblocked": "{{GENDER:$1|Cet utilisateur|Cette utilisatrice}} est bloqué{{GENDER:$1||e}}. La connexion n’est pas autorisée.",
        "password-login-forbidden": "L’utilisation de ce nom d’utilisateur ou de ce mot de passe a été interdite.",
        "mailmypassword": "Réinitialiser le mot de passe",
        "passwordremindertitle": "Nouveau mot de passe temporaire pour {{SITENAME}}",
-       "passwordremindertext": "Quelqu’un (depuis l’adresse IP $1) a demandé un nouveau mot de\npasse pour {{SITENAME}} ($4). Un mot de passe temporaire pour l’utilisateur\n« $2 » a été créé et est « $3 ». Si cela était votre intention,\nvous devrez vous connecter et choisir un nouveau mot de passe.\nVotre mot de passe temporaire expirera dans $5 jour{{PLURAL:$5||s}}.\n\nSi vous n’êtes pas l’auteur de cette demande, ou si vous vous avez retrouvé votre mot de passe et ne souhaitez plus en changer, vous pouvez ignorer ce message\net continuer à utiliser votre ancien mot de passe.",
+       "passwordremindertext": "Quelqu’un (depuis l’adresse IP $1) a demandé un nouveau mot de passe\npour {{SITENAME}} ($4). Un mot de passe temporaire pour l’utilisateur\n« $2 » a été créé et défini comme « $3 ». Si c’était bien votre intention,\nvous devrez vous connecter et choisir un nouveau mot de passe.\nVotre mot de passe temporaire expirera dans $5 jour{{PLURAL:$5||s}}.\n\nSi vous n’êtes pas l’auteur de cette demande ou si vous vous avez retrouvé votre\nmot de passe et ne souhaitez plus en changer, vous pouvez ignorer ce message et\ncontinuer à utiliser votre ancien mot de passe.",
        "noemail": "Aucune adresse de courriel n’a été enregistrée pour l’utilisat{{GENDER:$1|eur|rice}} « $1 ».",
        "noemailcreate": "Vous devez fournir une adresse de courriel valide",
        "passwordsent": "Un nouveau mot de passe a été envoyé à l’adresse de courriel de l’utilisat{{GENDER:$1|eur|rice}} « $1 ».\nVeuillez vous reconnecter après l’avoir reçu.",
        "botpasswords-label-grants": "Droits applicables :",
        "botpasswords-help-grants": "Les autorisations permettent d’accéder aux droits déjà accordés à votre compte utilisateur. Activer une autorisation ici ne fournit l’accès à aucun droit que votre compte utilisateur n’aurait pas par ailleurs. Voyez le [[Special:ListGrants|tableau des autorisations]] pour plus d’informations.",
        "botpasswords-label-grants-column": "Accordé",
-       "botpasswords-bad-appid": "Le nom de robot « $1 » n’est pas valide.",
+       "botpasswords-bad-appid": "Le nom de robot « $1 » n’est pas valide.",
        "botpasswords-insert-failed": "Échec de l’ajout du nom de robot « $1 ». A-t-il déjà été ajouté ?",
        "botpasswords-update-failed": "Échec à la mise à jour du nom de robot « $1 ». A-t-il déjà été supprimé ?",
        "botpasswords-created-title": "Mot de passe de robots créé",
        "botpasswords-no-provider": "BotPasswordsSessionProvider n’est pas disponible.",
        "botpasswords-restriction-failed": "Les restrictions de mot de passe de robots empêchent cette connexion.",
        "botpasswords-invalid-name": "Le nom d’utilisateur spécifié ne contient pas de séparateur de mot de passe de robots (« $1 »).",
-       "botpasswords-not-exist": "L’{{GENDER:$1|utilisateur|utilisatrice}} « $1 » n’a pas de mot de passe de robot nommé « $2 ».",
-       "botpasswords-needs-reset": "Le mot de passe du robot de nom « $2 » de l’utilisat{{GENDER:$1|eur|rice}} « $1 » doit être réinitialisé.",
+       "botpasswords-not-exist": "L’utilisat{{GENDER:$1|eur|rice}} « $1 » n’a pas de mot de passe de robot nommé « $2 ».",
+       "botpasswords-needs-reset": "Le mot de passe du robot nommé « $2 » de l’utilisat{{GENDER:$1|eur|rice}} « $1 » doit être réinitialisé.",
        "botpasswords-locked": "Vous ne pouvez pas vous connecter avec un mot de passe de robot, car votre compte est bloqué.",
        "resetpass_forbidden": "Les mots de passe ne peuvent pas être changés",
        "resetpass_forbidden-reason": "Les mots de passe ne peuvent pas être modifiés : $1",
        "resetpass-abort-generic": "La modification du mot de passe a été annulée par une extension.",
        "resetpass-expired": "Votre mot de passe a expiré. Veuillez en fournir un nouveau pour vous connecter.",
        "resetpass-expired-soft": "Votre mot de passe a expiré, et doit être modifié. Veuillez en choisir un nouveau maintenant ou cliquer sur « {{int:authprovider-resetpass-skip-label}} » pour le faire plus tard.",
-       "resetpass-validity": "Votre mot de passe est non valide : $1\n\nVeuillez entrer un nouveau mot de passe pour vous connecter.",
-       "resetpass-validity-soft": "Votre mot de passe n’est pas valide : $1\n\nVeuillez choisir un nouveau mot de passe maintenant, ou cliquez sur « {{int:authprovider-resetpass-skip-label}} » pour le modifier plus tard.",
+       "resetpass-validity": "Votre mot de passe est non valide: $1\n\nVeuillez entrer un nouveau mot de passe pour vous connecter.",
+       "resetpass-validity-soft": "Votre mot de passe n’est pas valide: $1\n\nVeuillez choisir un nouveau mot de passe maintenant, ou cliquez sur « {{int:authprovider-resetpass-skip-label}} » pour le modifier plus tard.",
        "passwordreset": "Réinitialisation du mot de passe",
        "passwordreset-text-one": "Remplissez ce formulaire pour réinitialiser votre mot de passe.",
        "passwordreset-text-many": "{{PLURAL:$1|Remplissez un des champs pour recevoir un mot de passe temporaire par courriel.}}",
        "preview": "Prévisualisation",
        "showpreview": "Prévisualiser",
        "showdiff": "Voir les modifications",
-       "blankarticle": "<strong>Attention :</strong> la page que vous créez est vide.\nSi vous cliquez de nouveau sur « $1 », la page sera créée sans aucun contenu.",
+       "blankarticle": "<strong>Attention:</strong> la page que vous créez est vide.\nSi vous cliquez de nouveau sur « $1 », la page sera créée sans aucun contenu.",
        "anoneditwarning": "<strong>Attention :</strong> vous n’êtes pas connecté(e). Votre adresse IP sera visible de tout le monde si vous faites des modifications. Si vous <strong>[$1 vous connectez]</strong> ou <strong>[$2 créez un compte]</strong>, vos modifications seront attribuées à votre propre nom d’utilisateur(rice) et vous aurez d’autres avantages.",
        "anonpreviewwarning": "<em>Vous n’êtes pas connecté(e). Sauvegarder enregistrera votre adresse IP dans l’historique des modifications de la page.</em>",
        "missingsummary": "<strong>Rappel :</strong> vous n’avez pas encore fourni le résumé de votre modification.\nSi vous cliquez de nouveau sur le bouton « $1 », vos modifications seront sauvegardées sans résumé.",
-       "selfredirect": "<strong>Attention :</strong> vous êtes en train de rediriger la page vers elle-même.\nIl se peut que vous ayez spécifié la mauvaise cible pour la redirection, ou que vous modifiez peut-être la mauvaise page.\nSi vous cliquez de nouveau sur « $1 », la redirection sera tout de même créée.",
+       "selfredirect": "<strong>Attention:</strong> vous êtes en train de rediriger la page vers elle-même.\nIl se peut que vous ayez spécifié la mauvaise cible pour la redirection, ou que vous modifiez peut-être la mauvaise page.\nSi vous cliquez de nouveau sur « $1 », la redirection sera tout de même créée.",
        "missingcommenttext": "Veuillez entrer un commentaire.",
-       "missingcommentheader": "<strong>Rappel :</strong> vous n’avez pas fourni de sujet pour ce commentaire.\nSi vous cliquez de nouveau sur « {{int:Savearticle}} », votre modification sera enregistrée sans sujet.",
+       "missingcommentheader": "<strong>Rappel :</strong> vous n’avez pas fourni de sujet pour ce commentaire.\nSi vous cliquez de nouveau sur « $1 », votre modification sera enregistrée sans sujet.",
        "summary-preview": "Aperçu du résumé de modification :",
        "subject-preview": "Aperçu du sujet :",
        "previewerrortext": "Une erreur s’est produite lors de la tentative de prévisualisation de vos modifications.",
        "blockedtitle": "L’utilisateur est bloqué.",
-       "blocked-email-user": "<strong>Votre nom d’utilisateur a été bloqué pour l’envoi de courriels. Vous pouvez toujours modifier d’autres pages sur ce wiki.</strong> Vous pouvez voir tous les détails du blocage sur [[Special:MyContributions|contributions du compte]].\n\nCe blocage a été fait par $1.\n\nLe motif fourni est <em>$2</em>.\n\n* Début du blocage : $8\n* Expiration du blocage : $6\n* Cible souhaitée du blocage : $7\n* ID du blocage #$5",
-       "blockedtext-partial": "<strong>Votre nom d’utilisateur ou votre adresse IP a été bloqué pour effectuer des modifications sur cette page. Vous pouvez toujours modifier d’autres pages sur ce wiki.</strong> Vous pouvez voir tous les détails sur ce blocage sur [[Special:MyContributions|contributions du compte]].\n\nLe blocage a été effectué par $1.\n\nLe motif fourni est <em>$2</em>.\n\n* Début du blocage : $8\n* Expiration du blocage : $6\n* Cible souhaitée du blocage : $7\n* ID du blocage #$5",
-       "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é ne vous a pas été bloquée.\nVotre adresse IP actuelle est $3 et votre identifiant de blocage est $5.\nVeuillez inclure tous les détails ci-dessus dans chacune des 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é « {{int:emailuser}} » que si vous avez une adresse de courriel validée dans vos [[Special:Preferences|préférences]] et que cette fonctionnalité ne vous a pas été désactivée.\n\nVotre adresse IP actuelle est $3, et le numéro de blocage est $5.\nVeuillez inclure tous les détails ci-dessus dans chacune des requêtes que vous ferez.",
+       "blocked-email-user": "<strong>Votre nom d’utilisateur a été bloqué pour l’envoi de courriels. Vous pouvez toujours modifier d’autres pages sur ce wiki.</strong> Vous pouvez voir tous les détails du blocage sur [[Special:MyContributions|contributions du compte]].\n\nCe blocage a été fait par $1.\n\nLe motif fourni est <em>$2</em>.\n\n* Début du blocage : $8\n* Expiration du blocage : $6\n* Cible souhaitée du blocage : $7\n* ID du blocage nº $5",
+       "blockedtext-partial": "<strong>Votre nom d’utilisateur ou votre adresse IP a été bloqué pour effectuer des modifications sur cette page. Vous pouvez toujours modifier d’autres pages sur ce wiki.</strong> Vous pouvez voir tous les détails sur ce blocage sur [[Special:MyContributions|contributions du compte]].\n\nLe blocage a été effectué par $1.\n\nLe motif fourni est <em>$2</em>.\n\n* Début du blocage : $8\n* Expiration du blocage : $6\n* Cible souhaitée du blocage : $7\n* ID du blocage nº $5",
+       "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é ne vous a pas été bloquée.\nVotre adresse IP actuelle est $3 et votre identifiant de blocage est $5.\nVeuillez inclure tous les détails ci-dessus dans chacune des 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é « {{int:emailuser}} » que si vous avez une adresse de courriel validée dans vos [[Special:Preferences|préférences]] et que cette fonctionnalité ne vous a pas été désactivée.\n\nVotre adresse IP actuelle est $3, et le numéro de blocage est $5.\nVeuillez inclure tous les détails ci-dessus dans chacune des requêtes que vous ferez.",
        "systemblockedtext": "Votre nom d'utilisateur ou votre adresse IP ont été bloqués automatiquement par MediaWiki.\nLa raison donnée est la suivante:\n\n: <em>$2</em>.\n\n* Le début du blocage: $8\n* Expiration du délai de blocage: $6\n* Elément concerné: $7\n\nVotre adresse IP actuelle est $3.\nVeuillez inclure tous les détails ci-dessus dans chacune des requêtes que vous ferez.",
        "blockednoreason": "aucune raison donnée",
-       "blockedtext-composite": "<strong>Votre nom d'utilisateur ou votre adresse IP ont été bloqués.</strong>\n\nLa raison invoquées est :\n\n:<em>$2</em>.\n\n* Début du blocage : $8\n* Expiration du blocage le plus long : $6\n\n* $5\n\nVotre adresse IP actuelle est $3.\nVeuillez inclure tous les détails ci-dessus dans chaque demande que vous ferez.",
-       "blockedtext-composite-ids": "ID de bloc pertinents : $1 (votre adresse IP peut aussi être en liste noire)",
+       "blockedtext-composite": "<strong>Votre nom d'utilisateur ou votre adresse IP ont été bloqués.</strong>\n\nLa raison invoquée est :\n\n: <em>$2</em>.\n\n* Début du blocage : $8\n* Expiration du blocage le plus long : $6\n* $5\n\nVotre adresse IP actuelle est $3.\nVeuillez inclure tous les détails ci-dessus dans chaque demande que vous ferez.",
+       "blockedtext-composite-ids": "ID de bloc pertinents: $1 (votre adresse IP peut aussi être en liste noire)",
        "blockedtext-composite-no-ids": "Votre adresse IP apparaît dans plusieurs listes noires",
        "blockedtext-composite-reason": "Il existe plusieurs blocages sur votre compte et/ou votre adresse IP",
        "whitelistedittext": "Vous devez vous $1 pour avoir la permission de modifier le contenu.",
        "newarticletext": "Vous avez suivi un lien vers une page qui n’existe pas encore. \nAfin de créer cette page, entrez votre texte dans la boîte ci-après (vous pouvez consulter [$1 la page d’aide] pour plus d’informations). \nSi vous êtes arrivé{{GENDER:||e}} ici par erreur, cliquez sur le bouton <strong>Retour</strong> de votre navigateur.",
        "anontalkpagetext": "----\n<em>Vous êtes sur la page de discussion d’un utilisateur anonyme qui n’a pas encore créé de compte ou qui n’en utilise pas</em>.\nPour cette raison, nous devons utiliser son adresse IP pour l'identifier.\nUne telle adresse IP peut être partagée par plusieurs utilisateurs.\nSi vous êtes un{{GENDER:||e|}} utilisat{{GENDER:|eur|rice|eur}} anonyme et si vous constatez que des commentaires qui ne vous concernent pas vous ont été adressés, vous pouvez [[Special:CreateAccount|créer un compte]] ou [[Special:UserLogin|vous connecter]] afin d’éviter toute confusion future avec d’autres contributeurs anonymes.",
        "noarticletext": "Il n’y a pour l’instant aucun texte sur cette page.\nVous pouvez [[Special:Search/{{PAGENAME}}|lancer une recherche sur ce titre]] dans les autres pages,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rechercher dans les opérations liées]\nou [{{fullurl:{{FULLPAGENAME}}|action=edit}} créer cette page]</span>.",
-       "noarticletext-nopermission": "Il n'y a pour l'instant aucun texte sur cette page.\nVous pouvez [[Special:Search/{{PAGENAME}}|faire une recherche sur ce titre]] dans les autres pages,\nou <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rechercher dans les journaux associés]</span>, mais vous n'avez pas la permission de créer cette page.",
-       "missing-revision": "La révision nº $1 de la page intitulée « {{FULLPAGENAME}} » n’existe pas.\n\nCela survient en général en suivant un lien historique désuet vers une page qui a été supprimée.\nVous pouvez trouver plus de détails dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
+       "noarticletext-nopermission": "Il n’y a pour l’instant aucun texte sur cette page.\nVous pouvez [[Special:Search/{{PAGENAME}}|faire une recherche sur ce titre]] dans les autres pages,\nou <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} rechercher dans les journaux associés]</span>, mais vous n’avez pas la permission de créer cette page.",
+       "missing-revision": "La révision nº $1 de la page intitulée « {{FULLPAGENAME}} » n’existe pas.\n\nCela survient en général en suivant un lien historique désuet vers une page qui a été supprimée.\nVous pouvez trouver plus de détails dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
        "userpage-userdoesnotexist": "Le compte utilisateur « <nowiki>$1</nowiki> » n’est pas enregistré. Veuillez vérifier que vous voulez créer cette page.",
        "userpage-userdoesnotexist-view": "Le compte utilisateur « $1 » n'est pas enregistré.",
-       "blocked-notice-logextract": "Cet utilisateur est actuellement bloqué.\nLa dernière entrée du journal des blocages est affichée ci-dessous pour référence :",
-       "clearyourcache": "<strong>Note :</strong> après avoir enregistré vos modifications, il se peut que vous deviez forcer le rechargement complet du cache de votre navigateur pour voir les changements.\n* <strong>Firefox / Safari :</strong> maintenez la touche <em>Maj</em> (<em>Shift</em>) en cliquant sur le bouton <em>Actualiser</em> ou pressez <em>Ctrl-F5</em> ou <em>Ctrl-R</em> (<em>⌘-R</em> sur un Mac) \n* <strong>Google Chrome :</strong> appuyez sur <em>Ctrl-Maj-R</em> (<em>⌘-Shift-R</em> sur un Mac) \n* <strong>Internet Explorer :</strong> maintenez la touche <em>Ctrl</em> en cliquant sur le bouton <em>Actualiser</em> ou pressez <em>Ctrl-F5</em> \n* <strong>Opera :</strong> allez dans <em>Menu → Settings</em> (<em>Opera → Préférences</em> sur un Mac) et ensuite à <em>Confidentialité & sécurité → Effacer les données d’exploration → Images et fichiers en cache</em>.",
+       "blocked-notice-logextract": "Cet utilisateur est actuellement bloqué.\nLa dernière entrée du journal des blocages est affichée ci-dessous pour référence:",
+       "clearyourcache": "<strong>Note :</strong> après avoir enregistré vos modifications, il se peut que vous deviez forcer le rechargement complet du cache de votre navigateur pour voir les changements.\n* <strong>Firefox / Safari :</strong> maintenez la touche <em>Maj</em> (<em>Shift</em>) en cliquant sur le bouton <em>Actualiser</em> ou pressez <em>Ctrl-F5</em> ou <em>Ctrl-R</em> (<em>⌘-R</em> sur un Mac).\n* <strong>Google Chrome :</strong> appuyez sur <em>Ctrl-Maj-R</em> (<em>⌘-Shift-R</em> sur un Mac).\n* <strong>Internet Explorer :</strong> maintenez la touche <em>Ctrl</em> en cliquant sur le bouton <em>Actualiser</em> ou pressez <em>Ctrl-F5</em>.\n* <strong>Opera :</strong> allez dans <em>Menu → Settings</em> (<em>Opera → Préférences</em> sur un Mac) et ensuite à <em>Confidentialité et sécurité → Effacer les données d’exploration → Images et fichiers en cache</em>.",
        "usercssyoucanpreview": "<strong>Astuce :</strong> utilisez le bouton « {{int:showpreview}} » pour tester votre nouvelle feuille CSS avant de l’enregistrer.",
-       "userjsonyoucanpreview": "<strong>Conseil :</strong> Utiliser le bouton « {{int:showpreview}} » pour tester votre nouveau JSON avant enregistrement.",
+       "userjsonyoucanpreview": "<strong>Conseil :</strong> utilisez le bouton « {{int:showpreview}} » pour tester votre nouveau JSON avant enregistrement.",
        "userjsyoucanpreview": "<strong>Astuce :</strong> utilisez le bouton « {{int:showpreview}} » pour tester votre nouvelle feuille JavaScript avant de l’enregistrer.",
-       "usercsspreview": "<strong>Rappelez-vous que vous ne faites que prévisualiser votre propre feuille CSS. \nElle n’a pas encore été enregistrée !</strong>",
+       "usercsspreview": "<strong>Rappelez-vous que vous ne faites que prévisualiser votre propre feuille CSS.\nElle n’a pas encore été enregistrée !</strong>",
        "userjsonpreview": "<strong>Rappelez-vous que vous êtes seulement en train de tester/voir un aperçu de votre configuration utilisateur JSON.\nElle n’a pas encore été enregistrée !</strong>",
-       "userjspreview": "<strong>Rappelez-vous que vous ne faites que visualiser ou tester votre code JavaScript.\nIl n’a pas encore été enregistré !</strong>",
-       "sitecsspreview": "<strong>Rappelez-vous que vous ne faites que prévisualiser cette feuille de style. \nElle n’a pas encore été enregistrée !</strong>",
+       "userjspreview": "<strong>Rappelez-vous que vous ne faites que visualiser ou tester votre code JavaScript.\nIl n’a pas encore été enregistré!</strong>",
+       "sitecsspreview": "<strong>Rappelez-vous que vous ne faites que prévisualiser cette feuille de style. \nElle n’a pas encore été enregistrée!</strong>",
        "sitejsonpreview": "<strong>Souvenez-vous que vous ne faites que regarder un aperçu de cette configuration JSON.\nElle n’a pas encore été enregistrée !</strong>",
-       "sitejspreview": "<strong>Rappelez-vous que vous ne faites que prévisualiser ce code JavaScript. \nIl n’a pas encore été enregistré !</strong>",
-       "userinvalidconfigtitle": "<strong>Attention :</strong> il n’existe pas d’habillage « $1 ». \nLes pages personnelles avec extensions .css, .json et .js utilisent des titres en minuscules, par exemple {{ns:user}}:Foo/vector.css et non {{ns:user}}:Foo/Vector.css.",
+       "sitejspreview": "<strong>Rappelez-vous que vous ne faites que prévisualiser ce code JavaScript.\nIl n’a pas encore été enregistré !</strong>",
+       "userinvalidconfigtitle": "<strong>Attention :</strong> il n’existe pas d’habillage « $1 ».\nLes pages personnelles avec extensions .css, .json et .js utilisent des titres en minuscules, par exemple <tt>{{ns:user}}:Foo/vector.css</tt> et non <tt>{{ns:user}}:Foo/Vector.css</tt>.",
        "updated": "(Mis à jour)",
        "note": "<strong>Note :</strong>",
        "previewnote": "<strong>Rappelez-vous que ce n’est qu’une prévisualisation.</strong>\nVos modifications n’ont pas encore été enregistrées !",
        "continue-editing": "Aller à la zone de modification",
        "previewconflict": "Cette prévisualisation montre le texte de la boîte supérieure de modification tel qu’il apparaîtra si vous choisissez de le publier.",
-       "session_fail_preview": "Désolé, nous ne pouvons enregistrer votre modification à cause d’une perte d’informations concernant votre session.\n\nVous avez peut-être été déconnecté. <strong>Veuillez vérifier que vous êtes toujours connecté et réessayer.</strong>\nSi cela échoue de nouveau, essayez en vous [[Special:UserLogout|déconnectant]], puis en vous reconnectant, et vérifiez que votre navigateur accepte les témoins (''cookies'') de ce site.",
+       "session_fail_preview": "Désolé, nous ne pouvons enregistrer votre modification à cause d’une perte d’informations concernant votre session.\n\nVous avez peut-être été déconnecté. <strong>Veuillez vérifier que vous êtes toujours connecté et réessayer.</strong>\nSi cela échoue de nouveau, essayez en vous [[Special:UserLogout|déconnectant]] puis en vous reconnectant. Vérifiez également que votre navigateur accepte les témoins (''cookies'') de ce site.",
        "session_fail_preview_html": "Désolé, nous ne pouvons enregistrer votre modification à cause d’une perte d’informations concernant votre session.\n\n<em>Parce que {{SITENAME}} a activé le HTML brut, la prévisualisation est masquée afin de prévenir les attaques par JavaScript.</em>\n\n<strong>Si la tentative de modification est légitime, veuillez réessayer.</strong>\nSi cela échoue de nouveau, [[Special:UserLogout|déconnectez-vous]], puis reconnectez-vous, et vérifiez que votre navigateur accepte les témoins (''cookies'') de ce site.",
        "token_suffix_mismatch": "<strong>Votre modification n’a pas été acceptée car votre navigateur a mal codé les caractères de ponctuation dans l’identifiant de modification.</strong>\nCe rejet est nécessaire pour empêcher la corruption du texte de la page.\nCe problème se produit parfois lorsque vous utilisez un serveur mandataire anonyme problématique basé sur le web.",
        "edit_form_incomplete": "<strong>Certaines parties du formulaire de modification n’ont pas atteint le serveur, vérifiez que vos modifications sont intactes et essayez à nouveau.</strong>",
        "editingsection": "Modification de $1 (section)",
        "editingcomment": "Modification de $1 (nouvelle section)",
        "editconflict": "Conflit de modification : $1",
-       "explainconflict": "Cette page a été changée après que vous avez commencé à la modifier.\nLa zone de modification supérieure contient le texte tel qu’il est actuellement enregistré dans la base de données.\nVos modifications apparaissent dans la zone de modification inférieure.\nVous allez devoir fusionner vos modifications dans le texte existant.\n<strong>Seul</strong> le texte de la zone supérieure sera sauvegardé si vous cliquez sur « $1 ».",
+       "explainconflict": "Cette page a été changée après que vous avez commencé à la modifier.\nLa zone de modification supérieure contient le texte tel qu’il est actuellement enregistré dans la base de données.\nVos modifications apparaissent dans la zone de modification inférieure.\nVous allez devoir fusionner vos modifications dans le texte existant.\n<strong>Seul</strong> le texte de la zone supérieure sera sauvegardé si vous cliquez sur « $1 ».",
        "yourtext": "Votre texte",
        "storedversion": "La version enregistrée",
        "editingold": "<strong>Attention : vous êtes en train de modifier une ancienne version de cette page.</strong>\nSi vous la publiez, toutes les modifications effectuées depuis cette version seront perdues.",
-       "unicode-support-fail": "Votre navigateur semble ne pas rendre en charge l'Unicode. Ceci est nécessaire pour modifier les pages, aussi vos modifications n'ont pas été sauvegardées.",
+       "unicode-support-fail": "Votre navigateur semble ne pas rendre en charge lUnicode. Ceci est nécessaire pour modifier les pages, aussi vos modifications n'ont pas été sauvegardées.",
        "yourdiff": "Différences",
-       "copyrightwarning": "Toutes les contributions à {{SITENAME}} sont considérées comme publiées sous les termes de la $2 (voir $1 pour plus de détails). \nSi vous ne désirez pas que vos écrits soient modifiés et distribués à volonté, merci de ne pas les soumettre ici.<br /> \nVous nous promettez aussi que vous avez écrit ceci vous-même, ou que vous l’avez copié d’une source provenant du domaine public ou d’une ressource libre similaire. \n<strong>N’UTILISEZ PAS DE TRAVAUX SOUS DROIT D’AUTEUR SANS AUTORISATION EXPRESSE !</strong>",
-       "copyrightwarning2": "Notez bien que toutes les contributions à {{SITENAME}} peuvent être modifiées, transformées ou supprimées par d’autres utilisateurs. \nSi vous ne désirez pas que vos écrits soient modifiés contre votre gré, merci de ne pas les soumettre ici.<br /> \nVous nous promettez aussi que vous avez écrit ceci vous-même, ou que vous l’avez copié d’une source provenant du domaine public, ou d’une ressource libre. (voir $1 pour plus de détails).\n<strong>N’UTILISEZ PAS DE TRAVAUX SOUS DROIT D’AUTEUR SANS AUTORISATION EXPRESSE !</strong>",
+       "copyrightwarning": "Toutes les contributions à {{SITENAME}} sont considérées comme publiées sous les termes de la $2 (voir $1 pour plus de détails). \nSi vous ne désirez pas que vos écrits soient modifiés et distribués à volonté, merci de ne pas les soumettre ici.<br /> \nVous nous promettez aussi que vous avez écrit ceci vous-même, ou que vous l’avez copié d’une source provenant du domaine public ou d’une ressource libre similaire.\n<strong>N’UTILISEZ PAS DE TRAVAUX SOUS DROIT D’AUTEUR SANS AUTORISATION EXPRESSE !</strong>",
+       "copyrightwarning2": "Notez bien que toutes les contributions à {{SITENAME}} peuvent être modifiées, transformées ou supprimées par d’autres utilisateurs.\nSi vous ne désirez pas que vos écrits soient modifiés contre votre gré, merci de ne pas les soumettre ici.<br />\nVous nous promettez aussi que vous avez écrit ceci vous-même ou que vous l’avez copié d’une source provenant du domaine public ou d’une ressource libre (voir $1 pour plus de détails).\n<strong>N’UTILISEZ PAS DE TRAVAUX SOUS DROIT D’AUTEUR SANS AUTORISATION EXPRESSE !</strong>",
        "editpage-cannot-use-custom-model": "Le modèle de contenu de cette page ne peut pas être modifié.",
        "longpageerror": "<strong>Erreur : Le texte que vous avez soumis fait {{PLURAL:$1|un Kio|$1 Kio}}, ce qui dépasse la limite fixée à {{PLURAL:$2|un Kio|$2 Kio}}.</strong>\nIl ne peut pas être sauvegardé.",
-       "readonlywarning": "<strong>AVERTISSEMENT : la base de données a été verrouillée pour des opérations de maintenance. Vous ne pouvez donc pas publier vos modifications pour l’instant.</strong>\nVous pouvez copier et coller votre texte dans un fichier texte et l’enregistrer pour plus tard.\n\nL’administrateur système ayant verrouillé la base de données a donné l’explication suivante : $1",
-       "protectedpagewarning": "<strong>AVERTISSEMENT : cette page est protégée afin que seuls les utilisateurs ayant le statut d'administrateur puissent la modifier.</strong>\nLa dernière entrée du journal est affichée ci-dessous pour référence :",
-       "semiprotectedpagewarning": "<strong>Note :</strong>Cette page a été protégée pour que seuls les contributeurs confirmés automatiquement puissent la modifier. \nLa dernière entrée du journal est affichée ci-dessous pour référence :",
-       "cascadeprotectedwarning": "<strong>ATTENTION :</strong> Cette page a été protégée de manière à ce que seuls les utilisateurs avec [[Special:ListGroupRights|des droits spécifiques]] puissent la modifier car elle est incluse dans {{PLURAL:$1|la page suivante, protégée en cascade|les pages suivantes, protégées en cascade}} :",
-       "titleprotectedwarning": "<strong>ATTENTION : Cette page a été protégée de telle manière que des [[Special:ListGroupRights|droits spécifiques]] sont requis pour pouvoir la créer.</strong> \nLa dernière entrée du journal est affichée ci-dessous pour référence :",
+       "readonlywarning": "<strong>AVERTISSEMENT : la base de données a été verrouillée pour des opérations de maintenance. Vous ne pouvez donc pas publier vos modifications pour l’instant.</strong>\nVous pouvez copier et coller votre texte dans un fichier texte et l’enregistrer pour plus tard.\n\nL’administrateur système ayant verrouillé la base de données a donné l’explication suivante : $1",
+       "protectedpagewarning": "<strong>AVERTISSEMENT : cette page est protégée afin que seuls les utilisateurs ayant le statut d’administrateur puissent la modifier.</strong>\nLa dernière entrée du journal est affichée ci-dessous pour référence :",
+       "semiprotectedpagewarning": "<strong>Note :</strong>Cette page a été protégée pour que seuls les contributeurs confirmés automatiquement puissent la modifier.\nLa dernière entrée du journal est affichée ci-dessous pour référence :",
+       "cascadeprotectedwarning": "<strong>ATTENTION :</strong> cette page a été protégée de manière à ce que seuls les utilisateurs avec [[Special:ListGroupRights|des droits spécifiques]] puissent la modifier car elle est incluse dans {{PLURAL:$1|la page suivante, protégée en cascade|les pages suivantes, protégées en cascade}} :",
+       "titleprotectedwarning": "<strong>ATTENTION : cette page a été protégée de telle manière que des [[Special:ListGroupRights|droits spécifiques]] sont requis pour pouvoir la créer.</strong>\nLa dernière entrée du journal est affichée ci-dessous pour référence :",
        "templatesused": "{{PLURAL:$1|Modèle utilisé|Modèles utilisés}} par cette page :",
        "templatesusedpreview": "{{PLURAL:$1|Modèle utilisé|Modèles utilisés}} dans cette prévisualisation :",
        "templatesusedsection": "{{PLURAL:$1|Modèle utilisé|Modèles utilisés}} dans cette section :",
        "edittools": "<!-- Tout texte entré ici sera affiché sous les boîtes de modification ou les formulaires de téléversement de fichier. -->",
        "edittools-upload": "—",
        "nocreatetext": "{{SITENAME}} a restreint la possibilité de créer de nouvelles pages.\nVous pouvez revenir en arrière et modifier une page existante, ou bien [[Special:UserLogin|vous connecter ou créer un compte]].",
-       "nocreate-loggedin": "Vous n'avez pas la permission de créer de nouvelles pages.",
+       "nocreate-loggedin": "Vous navez pas la permission de créer de nouvelles pages.",
        "sectioneditnotsupported-title": "Modification de section non prise en charge",
        "sectioneditnotsupported-text": "La modification d’une section n’est pas prise en charge pour cette page.",
        "modeleditnotsupported-title": "Modification non prise en charge",
        "modeleditnotsupported-text": "La modification n’est pas prise en charge pour le modèle de contenu $1.",
        "permissionserrors": "Erreur de permissions",
-       "permissionserrorstext": "Vous n'avez pas la permission d'effectuer l'opération demandée pour {{PLURAL:$1|la raison suivante|les raisons suivantes}} :",
-       "permissionserrorstext-withaction": "Vous ne pouvez pas $2, pour {{PLURAL:$1|la raison suivante|les raisons suivantes}} :",
+       "permissionserrorstext": "Vous n’avez pas la permission d'effectuer l'opération demandée pour {{PLURAL:$1|la raison suivante|les raisons suivantes}} :",
+       "permissionserrorstext-withaction": "Vous ne pouvez pas $2, pour {{PLURAL:$1|la raison suivante|les raisons suivantes}}:",
        "contentmodelediterror": "Vous ne pouvez pas modifier cette révision car son modèle de contenu est <code>$1</code>, ce qui diffère du modèle de contenu actuel de la page <code>$2</code>.",
-       "recreate-moveddeleted-warn": "<strong>Attention : vous êtes en train de recréer une page qui a été précédemment supprimée.</strong>\n\nAssurez-vous qu'il est pertinent de poursuivre les modifications sur cette page.\nLes journaux des suppressions et déplacements pour cette page sont fournis ici pour information :",
+       "recreate-moveddeleted-warn": "<strong>Attention : vous êtes en train de recréer une page qui a été précédemment supprimée.</strong>\n\nAssurez-vous qu’il est pertinent de poursuivre les modifications sur cette page.\nLes journaux des suppressions et déplacements pour cette page sont fournis ici pour information :",
        "moveddeleted-notice": "Cette page a été supprimée.\nLes journaux des suppressions, protections et déplacements pour la page sont fournis ci-dessous pour référence.",
        "moveddeleted-notice-recent": "Désolé, cette page a été récemment supprimée (dans les dernières 24 heures).\nLes journaux des suppressions, protections et déplacements pour la page sont fournis ci-dessous pour référence.",
        "log-fulllog": "Voir le journal complet",
        "edit-gone-missing": "N’a pas pu mettre à jour la page.\nIl semble qu’elle ait été supprimée.",
        "edit-conflict": "Conflit de modification.",
        "edit-no-change": "Votre modification a été ignorée car aucun changement n’a été apporté au texte.",
-       "edit-slots-cannot-add": "{{PLURAL:$1|L’emplacement suivant n’est pas supporté|Les emplacements suivants ne sont pas supportés}} ici : $2.",
-       "edit-slots-cannot-remove": "{{PLURAL:$1|L’emplacement suivant est obligatoire et ne peut pas être supprimé|Les emplacements suivants sont obligatoires et ne peuvent pas être supprimés}} : $2.",
-       "edit-slots-missing": "{{PLURAL:$1|L’emplacement suivant est absent|Les emplacements suivants sont absents}} : $2.",
+       "edit-slots-cannot-add": "{{PLURAL:$1|L’emplacement suivant n’est pas supporté|Les emplacements suivants ne sont pas supportés}} ici: $2.",
+       "edit-slots-cannot-remove": "{{PLURAL:$1|L’emplacement suivant est obligatoire et ne peut pas être supprimé|Les emplacements suivants sont obligatoires et ne peuvent pas être supprimés}}: $2.",
+       "edit-slots-missing": "{{PLURAL:$1|L’emplacement suivant est absent|Les emplacements suivants sont absents}}: $2.",
        "postedit-confirmation-created": "La page a été créée.",
        "postedit-confirmation-restored": "La page a été restaurée.",
        "postedit-confirmation-saved": "Votre modification a été enregistrée.",
        "content-not-allowed-here": "Le contenu « $1 » n’est pas autorisé sur la page [[:$2]] dans l’emplacement « $3 »",
        "editwarning-warning": "Quitter cette page vous fera perdre toutes les modifications que vous avez faites.\nSi vous êtes connecté{{GENDER:||e}}, vous pouvez désactiver cet avertissement dans la section « {{int:prefs-editing}} » de vos préférences.",
        "editpage-invalidcontentmodel-title": "Modèle de contenu non pris en charge",
-       "editpage-invalidcontentmodel-text": "Le modèle de contenu \"$1\" n'est pas pris en charge.",
+       "editpage-invalidcontentmodel-text": "Le modèle de contenu « $1 » n’est pas pris en charge.",
        "editpage-notsupportedcontentformat-title": "Format de contenu non pris en charge",
-       "editpage-notsupportedcontentformat-text": "Le format de contenu $1 n'est pas pris en charge par le modèle de contenu $2 .",
+       "editpage-notsupportedcontentformat-text": "Le format de contenu $1 nest pas pris en charge par le modèle de contenu $2 .",
        "slot-name-main": "Principal",
        "content-model-wikitext": "wikitexte",
        "content-model-text": "texte brut",
        "unsupported-content-diff": "Les diffs ne sont pas supportés pour le modèle de contenu $1.",
        "unsupported-content-diff2": "Les diffs entre les modèles de contenu $1 et $2 ne sont pas supportés sur ce wiki.",
        "deprecated-self-close-category": "Pages utilisant des balises HTML auto-fermantes non valides",
-       "deprecated-self-close-category-desc": "La page contient des balises HTML auto-fermantes non valides, comme <code>&lt;b/></code> ou <code>&lt;span/></code>. Le comportement de celles-ci changera prochainement pour être en accord avec la spécification HTML5, donc leur utilisation dans le wikitexte est désuète.",
-       "duplicate-args-warning": "<strong>Avertissement :</strong> [[:$1]] appelle [[:$2]] avec plus d'une valeur pour le paramètre « $3 ». Seule la dernière valeur fournie sera utilisée.",
+       "deprecated-self-close-category-desc": "La page contient des balises HTML auto-fermantes non valides, comme <code>&lt;b/></code> ou <code>&lt;span/></code>. Le comportement de celles-ci changera prochainement pour être en accord avec la spécification HTML5, donc leur utilisation dans le wikitexte est désormais désuète.",
+       "duplicate-args-warning": "<strong>Avertissement :</strong> [[:$1]] appelle [[:$2]] avec plus d'une valeur pour le paramètre « $3 ». Seule la dernière valeur fournie sera utilisée.",
        "duplicate-args-category": "Pages utilisant des arguments dupliqués dans les appels de modèle",
        "duplicate-args-category-desc": "La page contient des appels de modèle qui utilisent des arguments dupliqués, comme <code><nowiki>{{foo|bar=1|bar=2}}</nowiki></code> ou <code><nowiki>{{foo|bar|1=baz}}</nowiki></code>.",
        "expensive-parserfunction-warning": "<strong>Attention :</strong> cette page contient de trop nombreux appels à des fonctions coûteuses de l’analyseur syntaxique.\n\nIl devrait y avoir moins de $2 appel{{PLURAL:$2||s}}, alors qu’il y en a maintenant $1.",
-       "expensive-parserfunction-category": "Pages avec trop d'appels dispendieux aux fonctions de l'analyseur syntaxique",
+       "expensive-parserfunction-category": "Pages avec trop d’appels dispendieux aux fonctions de l’analyseur syntaxique",
        "post-expand-template-inclusion-warning": "<strong>Attention :</strong> cette page contient trop d’inclusions de modèles. Certaines inclusions ne seront pas effectuées.",
        "post-expand-template-inclusion-category": "Pages contenant trop d'inclusions de modèles",
-       "post-expand-template-argument-warning": "<strong>Attention :</strong> cette page contient au moins un paramètre de modèle dont la taille après expansion est trop importante. \nCes arguments n’ont donc pas été inclus.",
+       "post-expand-template-argument-warning": "<strong>Attention :</strong> cette page contient au moins un paramètre de modèle dont la taille après expansion est trop importante.\nCes arguments n’ont donc pas été inclus.",
        "post-expand-template-argument-category": "Pages contenant des paramètres de modèle non évalués",
        "parser-template-loop-warning": "Modèle en boucle détecté : [[$1]]",
        "template-loop-category": "Pages avec des boucles de modèle",
-       "template-loop-category-desc": "La page contient une boucle dans le modèle, c.à.d. un modèle qui s’appelle lui-même récursivement.",
-       "template-loop-warning": "<strong>Avertissement :</strong> Cette page appelle [[:$1]] ce qui provoque une boucle de modèles (un appel récursif infini).",
+       "template-loop-category-desc": "La page contient une boucle de modèle, c.à.d. un modèle qui s’appelle lui-même récursivement.",
+       "template-loop-warning": "<strong>Avertissement :</strong> cette page appelle [[:$1]] ce qui provoque une boucle de modèles (un appel récursif potentiellement infini).",
        "parser-template-recursion-depth-warning": "Limite de profondeur des appels récursifs de modèles dépassée ($1)",
        "language-converter-depth-warning": "Limite de profondeur du convertisseur de langue dépassée ($1)",
        "node-count-exceeded-category": "Pages dépassant le nombre de nœuds maximal",
        "expansion-depth-exceeded-category": "Pages dépassant la profondeur d'expansion maximale",
        "expansion-depth-exceeded-category-desc": "La page dépasse la profondeur d’expansion maximale.",
        "expansion-depth-exceeded-warning": "Page dépassant la profondeur d’expansion maximale",
-       "parser-unstrip-loop-warning": "Boucle non dépilable détectée",
-       "unstrip-depth-warning": "Limite de récursion non dépilable dépassée ($1)",
+       "parser-unstrip-loop-warning": "Boucle de développement (<code>unstrip</code>) détectée",
+       "unstrip-depth-warning": "Limite de récursion de développement (<code>unstrip</code>) dépassée ($1)",
        "unstrip-depth-category": "Pages où la limite de profondeur de développement est dépassée",
-       "unstrip-size-warning": "Limite de taille de développement dépassée ($1)",
+       "unstrip-size-warning": "Limite de taille de développement (<code>unstrip</code>) dépassée ($1)",
        "unstrip-size-category": "Pages où la limite de taille de développement est dépassée",
        "converter-manual-rule-error": "Erreur détectée dans la règle manuelle de conversion de langue",
-       "undo-success": "Cette modification va être annulée.\nVeuillez vérifier les différences ci-dessous, puis publier l’annulation si c’est bien ce que vous voulez faire.",
+       "undo-success": "La précédente modification va être annulée.\nVeuillez vérifier les différences ci-dessous, puis publier l’annulation ci-dessous si c’est bien ce que vous voulez faire.",
        "undo-failure": "Cette modification ne peut pas être défaite : cela entrerait en conflit avec les modifications intermédiaires.",
-       "undo-main-slot-only": "La modification n'a pas pu être annulée car elle implique un contenu en dehors de la tranche principale.",
+       "undo-main-slot-only": "La modification na pas pu être annulée car elle implique un contenu en dehors de la tranche principale.",
        "undo-norev": "La modification n’a pas pu être défaite parce qu’elle est inexistante ou qu’elle a été supprimée.",
        "undo-nochange": "Il semblerait que la modification ait déjà été annulée.",
        "undo-summary": "Annulation des modifications $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|discussion]])",
+       "undo-summary-anon": "Annuler la modification $1 de [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Annuler la révision $1 par un utilisateur masqué",
-       "cantcreateaccount-text": "La création de compte depuis cette adresse IP (<strong>$1</strong>) a été bloquée par [[User:$3|$3]]. \n\nLa raison donnée par $3 était : <em>$2</em>",
-       "cantcreateaccount-range-text": "La création de compte depuis les adresses IP de la plage <strong>$1</strong>, où se trouve votre adresse IP (<strong>$4</strong>), a été bloquée par [[User:$3|$3]].\n\nLe motif fourni par $3 est <em>$2</em>",
+       "cantcreateaccount-text": "La création de compte depuis cette adresse IP (<strong>$1</strong>) a été bloquée par [[User:$3|$3]]. \n\nLa raison donnée par $3 était: <em>$2</em>",
+       "cantcreateaccount-range-text": "La création de compte depuis les adresses IP de la plage <strong>$1</strong>, où se trouve votre adresse IP (<strong>$4</strong>), a été bloquée par [[User:$3|$3]].\n\nLe motif fourni par $3 est : <em>$2</em>",
        "viewpagelogs": "Voir les opérations sur cette page",
        "nohistory": "Il n’existe pas d’historique des modifications pour cette page.",
        "currentrev": "Version actuelle",
        "last": "diff",
        "page_first": "première",
        "page_last": "dernière",
-       "histlegend": "Sélection du diff : cochez les boutons radio des versions à comparer et appuyez sur entrée ou sur le bouton en bas.<br />\nLégende : <strong>({{int:cur}})</strong> = différence avec la dernière version, <strong>({{int:last}})</strong> = différence avec la version précédente, <strong>{{int:minoreditletter}}</strong> = modification mineure.",
-       "history-fieldset-title": "Filtrer les versions",
+       "histlegend": "Sélection du diff : cochez les boutons radio des versions à comparer et appuyez sur entrée ou sur le bouton en bas.<br />\nLégende : <strong>({{int:cur}})</strong> = différence avec la dernière version, <strong>({{int:last}})</strong> = différence avec la version précédente, <strong>{{int:minoreditletter}}</strong> = modification mineure.",
+       "history-fieldset-title": "Filtrer les révisions",
        "history-show-deleted": "Révision supprimée uniquement",
        "histfirst": "les plus anciennes",
        "histlast": "les plus récentes",
        "historysize": "($1 octet{{PLURAL:$1||s}})",
        "historyempty": "vide",
        "history-feed-title": "Historique des versions",
-       "history-feed-description": "Historique des versions pour cette page sur le wiki",
+       "history-feed-description": "Historique des révisions pour cette page sur le wiki",
        "history-feed-item-nocomment": "$1 le $2",
-       "history-feed-empty": "La page demandée n'existe pas.\nElle a peut-être été effacée ou renommée.\nEssayez de [[Special:Search|rechercher sur le wiki]] pour trouver de nouvelles pages en rapport avec le sujet.",
+       "history-feed-empty": "La page demandée nexiste pas.\nElle a peut-être été effacée ou renommée.\nEssayez de [[Special:Search|rechercher sur le wiki]] pour trouver de nouvelles pages en rapport avec le sujet.",
        "history-edit-tags": "Modifier les balises des versions sélectionnées",
        "rev-deleted-comment": "(résumé de modification retiré)",
        "rev-deleted-user": "(nom d'utilisateur retiré)",
        "rev-showdeleted": "afficher",
        "revisiondelete": "Supprimer ou restaurer des événements",
        "revdelete-nooldid-title": "Version cible non valide",
-       "revdelete-nooldid-text": "Vous n’avez pas précisé de révision(s) cible(s) pour cette fonction, ou bien la révision spécifiée n’existe pas, ou bien vous tentez de masquer la révision actuelle.",
+       "revdelete-nooldid-text": "Vous n’avez pas précisé de révision(s) cible(s) pour cette fonction, ou la révision spécifiée n’existe pas, ou bien vous tentez de masquer la révision actuelle.",
        "revdelete-no-file": "Le fichier spécifié n'existe pas.",
-       "revdelete-show-file-confirm": "Êtes-vous sûr{{GENDER:||e}} de vouloir voir la révision supprimée du fichier « <nowiki>$1</nowiki> » datant du $2 à $3 ?",
+       "revdelete-show-file-confirm": "Êtes-vous sûr{{GENDER:||e}} de vouloir voir la révision supprimée du fichier « <nowiki>$1</nowiki> » datant du $2 à $3 ?",
        "revdelete-show-file-submit": "Oui",
-       "revdelete-selected-text": "{{PLURAL:$1|Révision sélectionnée|Révisions sélectionnées}} de [[:$2]] :",
-       "revdelete-selected-file": "{{PLURAL:$1|Version de fichier sélectionnée|Versions de fichier sélectionnées}} de [[:$2]] :",
-       "logdelete-selected": "{{PLURAL:$1|Événement d'historique sélectionné|Événements d'historique sélectionnés}} :",
+       "revdelete-selected-text": "{{PLURAL:$1|Révision sélectionnée|Révisions sélectionnées}} de [[:$2]]:",
+       "revdelete-selected-file": "{{PLURAL:$1|Version de fichier sélectionnée|Versions de fichier sélectionnées}} de [[:$2]]:",
+       "logdelete-selected": "{{PLURAL:$1|Événement d’historique sélectionné|Événements d’historique sélectionnés}} :",
        "revdelete-text-text": "Les révisions supprimées continueront à apparaître dans l’historique de la page, mais une partie de leur contenu sera inaccessible au public.",
        "revdelete-text-file": "Les versions de fichier supprimées continueront à apparaître dans l’historique des fichiers, mais une partie de leur contenu sera indisponible au public.",
-       "logdelete-text": "Les Ã©vènements supprimés du journal continueront à apparaître dans les journaux, mais une partie de leur contenu sera indisponible au public.",
-       "revdelete-text-others": "Les autres administrateurs seront toujours en mesure d'accéder au contenu caché et le restaurer, à moins que des restrictions supplémentaires soient fixées.",
-       "revdelete-confirm": "Confirmez que vous voulez effectuer cette action, que vous en comprenez les conséquences, et que vous le faites en accord avec [[{{MediaWiki:Policy-url}}|les règles]].",
-       "revdelete-suppress-text": "La suppression ne doit être utilisée <strong>que</strong> dans les cas suivants :\n* informations potentiellement diffamatoires\n* informations personnelles inappropriées\n*: <em>adresse, numéro de téléphone, numéro de sécurité sociale, …</em>",
+       "logdelete-text": "Les Ã©vénements supprimés du journal continueront à apparaître dans les journaux, mais une partie de leur contenu sera indisponible au public.",
+       "revdelete-text-others": "Les autres administrateurs seront toujours en mesure daccéder au contenu caché et le restaurer, à moins que des restrictions supplémentaires soient fixées.",
+       "revdelete-confirm": "Confirmez que vous voulez effectuer cette action, que vous en comprenez les conséquences et que vous le faites en accord avec [[{{MediaWiki:Policy-url}}|les règles]].",
+       "revdelete-suppress-text": "La suppression ne doit être utilisée <strong>que</strong> dans les cas suivants:\n* informations potentiellement diffamatoires\n* informations personnelles inappropriées\n*: <em>adresse, numéro de téléphone, numéro de sécurité sociale, …</em>",
        "revdelete-legend": "Mettre en place des restrictions de visibilité",
        "revdelete-hide-text": "Texte de la révision",
        "revdelete-hide-image": "Masquer le contenu du fichier",
        "revdelete-hide-name": "Masquer la cible et les paramètres",
        "revdelete-hide-comment": "Résumé de modification",
-       "revdelete-hide-user": "Nom d’utilisateur/Adresse IP de l’éditeur",
-       "revdelete-hide-restricted": "Supprimer ces données aux administrateurs ainsi qu'aux autres",
+       "revdelete-hide-user": "Nom d’utilisateur / adresse IP de l’auteur",
+       "revdelete-hide-restricted": "Supprimer ces données aux administrateurs ainsi quaux autres",
        "revdelete-radio-same": "(ne pas changer)",
        "revdelete-radio-set": "Masqué",
        "revdelete-radio-unset": "Visible",
        "revdelete-suppress": "Masquer également les données pour les administrateurs",
        "revdelete-unsuppress": "Enlever les restrictions sur les versions restaurées",
-       "revdelete-log": "Motif :",
+       "revdelete-log": "Motif:",
        "revdelete-submit": "Appliquer {{PLURAL:$1|à la révision sélectionnée|aux révisions sélectionnées}}",
        "revdelete-success": "Visibilité des versions mise à jour.",
-       "revdelete-failure": "'''La visibilité de la version n'a pas pu être mise à jour :'''\n$1",
+       "revdelete-failure": "'''La visibilité de la version n'a pas pu être mise à jour:'''\n$1",
        "logdelete-success": "Visibilité du journal modifiée.",
        "logdelete-failure": "'''La visibilité du journal n'a pas pu être définie :'''\n$1",
        "revdel-restore": "modifier la visibilité",
        "diff-paragraph-moved-toold": "Paragraphe déplacé. Cliquer pour accéder à l’ancien emplacement.",
        "difference-missing-revision": "{{PLURAL:$2|Une révision|$2 révisions}} de cette différence ($1) {{PLURAL:$2|n’a pas été trouvée|n’ont pas été trouvées}}.\n\nCela survient en général en suivant un lien de différence désuet vers une page qui a été supprimée.\nVous pouvez trouver des détails dans le [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} journal des suppressions].",
        "searchresults": "Résultats de la recherche",
-       "search-filter-title-prefix": "Recherche seulement les pages dont le titre commence par « $1 »",
+       "search-filter-title-prefix": "Recherche seulement les pages dont le titre commence par « $1 »",
        "search-filter-title-prefix-reset": "Rechercher toutes les pages",
        "searchresults-title": "Résultats de recherche pour « $1 »",
        "titlematches": "Correspondances dans les titres des pages",
        "shown-title": "Afficher $1 résultat{{PLURAL:$1||s}} par page",
        "viewprevnext": "Voir ($1 {{int:pipe-separator}} $2) ($3)",
        "searchmenu-exists": "<strong>Il existe une page nommée « [[:$1]] » sur ce wiki.</strong> {{PLURAL:$2|0=|Voyez également les autres résultats de votre recherche.}}",
-       "searchmenu-new": "<strong>Créer la page « [[:$1|$1]] » sur ce wiki !</strong> {{PLURAL:$2|0=Voyez également la page trouvée avec votre recherche.|Voyez également les résultats de votre recherche.}}",
+       "searchmenu-new": "<strong>Créer la page « [[:$1|$1]] » sur ce wiki !</strong> {{PLURAL:$2|0=Voyez également la page trouvée avec votre recherche.|Voyez également les résultats de votre recherche.}}",
        "searchprofile-articles": "Pages de contenu",
        "searchprofile-images": "Multimédia",
        "searchprofile-everything": "Tout",
        "prefs-help-email": "L'adresse de courriel est facultative, mais elle est nécessaire pour réinitialiser votre mot de passe, en cas d'oubli.",
        "prefs-help-email-others": "Vous pouvez aussi choisir de laisser les autres vous contacter par courriel via un lien sur votre page de discussion ou page utilisateur. \nVotre adresse courriel n'est pas révélée quand les autres utilisateurs vous contactent.",
        "prefs-help-email-required": "Une adresse de courriel est requise.",
+       "prefs-help-requireemail": "Si coché, enverra seulement les courriels de réinitialisation des mots de passe si la personne qui réinitialise a fourni à la fois un nom d’utilisateur et un courriel pour ce compte.",
        "prefs-info": "Informations de base",
        "prefs-i18n": "Internationalisation",
        "prefs-signature": "Signature",
        "prefs-tokenwatchlist": "Jeton",
        "prefs-diffs": "Différences",
        "prefs-help-prefershttps": "Cette préférence sera effective lors de votre prochaine connexion.",
-       "prefswarning-warning": "Vous avez effectué des modifications dans vos préférences qui n’ont pas encore été enregistrées.\nSi vous quittez cette page sans cliquer sur « $1 », vos préférences ne seront pas mises à jour.",
+       "prefswarning-warning": "Vous avez effectué des modifications dans vos préférences qui n’ont pas encore été enregistrées.\nSi vous quittez cette page sans cliquer sur « $1 », vos préférences ne seront pas mises à jour.",
        "prefs-tabs-navigation-hint": "Astuce : Vous pouvez utiliser les flèches de gauche et de droite pour naviguer entre les onglets.",
        "userrights": "Droits des utilisateurs",
        "userrights-lookup-user": "Sélectionner un utilisateur",
        "userrights-expiry-options": "1 jour:1 day,1 semaine:1 week,1 mois:1 month,3 mois:3 montghs,6 mois:6 month,1 an:1 year",
        "userrights-invalid-expiry": "La date d'expiration pour le groupe « $1 » n'est pas valide.",
        "userrights-expiry-in-past": "La date d'expiration pour le groupe « $1 » est dépassée.",
-       "userrights-cannot-shorten-expiry": "Vous ne pouvez pas raccourcir la durée d’expiration de l’appartenance au groupe « $1 ». Seuls les utilisateurs disposant de l’autorisation d’ajouter et de supprimer ce groupe peuvent raccourcir les durées d’expiration.",
+       "userrights-cannot-shorten-expiry": "Vous ne pouvez pas raccourcir la durée d’expiration de l’appartenance au groupe « $1 ». Seuls les utilisateurs disposant de l’autorisation d’ajouter et de supprimer ce groupe peuvent raccourcir les durées d’expiration.",
        "userrights-conflict": "Conflit de modification des droits utilisateur ! Veuillez relire et confirmer vos modifications.",
        "group": "Groupe :",
        "group-user": "Utilisateurs",
        "right-applychangetags": "Appliquer [[Special:Tags|les balises]] avec ses propres modifications",
        "right-changetags": "Ajouter et supprimer de façon arbitraire [[Special:Tags|des balises]] sur des révisions individuelles et des entrées de journal",
        "right-deletechangetags": "Supprimer des [[Special:Tags|balises]] de la base de données",
-       "grant-generic": "ensemble de droits « $1 »",
+       "grant-generic": "ensemble de droits « $1 »",
        "grant-group-page-interaction": "Interagir avec des pages",
        "grant-group-file-interaction": "Interagir avec des médias",
        "grant-group-watchlist-interaction": "Interagir avec votre liste de suivi",
        "action-bigdelete": "supprimer des pages avec de grands historiques",
        "action-blockemail": "empêcher un utilisateur d’envoyer des courriels",
        "action-bot": "être traité comme un processus automatisé",
-       "action-editprotected": "modifier les pages protégées comme « {{int:protect-level-sysop}} »",
+       "action-editprotected": "modifier les pages protégées comme « {{int:protect-level-sysop}} »",
        "action-editsemiprotected": "modifier des pages protégées avec le statut « {{int:protect-level-autoconfirmed}} »",
        "action-editinterface": "modifier l’interface utilisateur",
        "action-editusercss": "modifier les fichiers CSS d’autres utilisateurs",
        "rcfilters-filter-user-experience-level-newcomer-label": "Nouveaux arrivants",
        "rcfilters-filter-user-experience-level-newcomer-description": "Éditeurs connectés ayant fait moins de 10 modifications ou ayant moins de 4 jours d’activité.",
        "rcfilters-filter-user-experience-level-learner-label": "Apprentis",
-       "rcfilters-filter-user-experience-level-learner-description": "Éditeurs connectés dont l’expérience se situe entre  « Nouveaux arrivants » et  « Utilisateurs expérimentés ».",
+       "rcfilters-filter-user-experience-level-learner-description": "Éditeurs connectés dont l’expérience se situe entre  « Nouveaux arrivants » et  « Utilisateurs expérimentés ».",
        "rcfilters-filter-user-experience-level-experienced-label": "Utilisateurs expérimentés",
        "rcfilters-filter-user-experience-level-experienced-description": "Éditeurs connectés avec plus de 500 modifications et 30 jours d’activité.",
        "rcfilters-filtergroup-automated": "Contributions automatisées",
        "rcfilters-filter-categorization-description": "Enregistrements de pages ajoutées ou supprimées des catégories.",
        "rcfilters-filter-logactions-label": "Actions tracées",
        "rcfilters-filter-logactions-description": "Actions d’administration, créations de compte, suppression de pages, téléchargements…",
-       "rcfilters-hideminor-conflicts-typeofchange-global": "Le filtre « Modifications mineures » est en conflit avec au moins un filtre de Type de modification, parce que certains types de modification ne peuvent être marqués comme « mineurs ». Les filtres en conflit sont marqués dans la zone Filtres actifs ci-dessus.",
-       "rcfilters-hideminor-conflicts-typeofchange": "Certains types de modification ne peuvent pas être qualifiés de « mineurs », donc ce filtre est en conflit avec les filtres de Type de modification suivants : $1",
-       "rcfilters-typeofchange-conflicts-hideminor": "Ce filtre de Type de modification est en conflit avec le filtre « Modifications mineures ». Certains type sde modification ne peuvent pas être indiqués comme « mineurs ».",
+       "rcfilters-hideminor-conflicts-typeofchange-global": "Le filtre « Modifications mineures » est en conflit avec au moins un filtre de Type de modification, parce que certains types de modification ne peuvent être marqués comme « mineurs ». Les filtres en conflit sont marqués dans la zone Filtres actifs ci-dessus.",
+       "rcfilters-hideminor-conflicts-typeofchange": "Certains types de modification ne peuvent pas être qualifiés de « mineurs », donc ce filtre est en conflit avec les filtres de Type de modification suivants : $1",
+       "rcfilters-typeofchange-conflicts-hideminor": "Ce filtre de Type de modification est en conflit avec le filtre « Modifications mineures ». Certains type sde modification ne peuvent pas être indiqués comme « mineurs ».",
        "rcfilters-filtergroup-lastrevision": "Dernières révisions",
        "rcfilters-filter-lastrevision-label": "Dernière révision",
        "rcfilters-filter-lastrevision-description": "Uniquement la dernière modification apportée à une page.",
        "rcfilters-filter-previousrevision-label": "Pas la dernière version",
-       "rcfilters-filter-previousrevision-description": "Toutes les modifications apportées à une page et qui ne concernent pas la « dernière version ».",
+       "rcfilters-filter-previousrevision-description": "Toutes les modifications apportées à une page et qui ne concernent pas la « dernière version ».",
        "rcfilters-filter-excluded": "Exclu",
        "rcfilters-tag-prefix-namespace-inverted": "<strong>:not</strong> $1",
        "rcfilters-exclude-button-off": "Exclure les sélectionnés",
        "uploadscripted": "Ce fichier contient du code HTML ou un script qui pourrait être interprété de façon incorrecte par un navigateur web.",
        "upload-scripted-pi-callback": "Impossible de charger un fichier qui contient des instructions de traitement de feuille de style XML.",
        "upload-scripted-dtd": "Impossible de téléverser des fichiers SVG qui contiennent une déclaration de DTD non standard.",
-       "uploaded-script-svg": "Élément scriptable « $1 » trouvé dans le fichier SVG téléversé.",
+       "uploaded-script-svg": "Élément scriptable « $1 » trouvé dans le fichier SVG téléversé.",
        "uploaded-hostile-svg": "CSS non sûr trouvé dans l’élément style d’un fichier SVG téléversé.",
        "uploaded-event-handler-on-svg": "Fixer des attributs de gestionnaire d’événement <code>$1=\"$2\"</code> n’est pas autorisé dans les fichiers SVG.",
        "uploaded-href-attribute-svg": "<a> les éléments ne peuvent être liés (href) qu’aux cibles de données : (fichier inclus), http:// ou https://, ou un fragment (#, même document). Pour les autres éléments, comme <image>, seuls data: et fragment sont autorisés. Essayez les images incluses lors de l’export de votre SVG. <code>&lt;$1 $2=\"$3\"&gt;</code> obtenu.",
        "uploaded-href-unsafe-target-svg": "Un href vers des données non sûres a été trouvé dans le fichier SVG téléversé : URI cible <code>&lt;$1 $2=\"$3\"&gt;</code>.",
-       "uploaded-animate-svg": "Balise « animate » trouvée, qui pourrait modifier le href en utilisant l’attribut « from » <code>&lt;$1 $2=\"$3\"&gt;</code> dans le fichier SVG téléversé.",
+       "uploaded-animate-svg": "Balise « animate » trouvée qui pourrait modifier le href en utilisant l’attribut « from » <code>&lt;$1 $2=\"$3\"&gt;</code> dans le fichier SVG téléversé.",
        "uploaded-setting-event-handler-svg": "Positionner les attributs du gestionnaire d’événements n'est pas possible, <code>&lt;$1 $2=\"$3\"&gt;</code> trouvé dans le fichier SVG téléversé.",
-       "uploaded-setting-href-svg": "L’utilisation de la balise « set » pour ajouter un attribut « href » à l’élément parent est interdite.",
-       "uploaded-wrong-setting-svg": "L’utilisation de la balise « set » pour ajouter une cible distante, de données ou de type script,  à un attribut quelconque, est interdite. <code>&lt;set to=\"$1\"&gt;</code> a été trouvé dans le fichier SVG téléversé.",
-       "uploaded-setting-handler-svg": "Les SVG qui positionnent l’attribut « handler » avec distant/données/script sont bloqués. <code>$1=\"$2\"</code> a été trouvé dans le fichier SVG téléversé.",
+       "uploaded-setting-href-svg": "L’utilisation de la balise « set » pour ajouter un attribut « href » à l’élément parent est interdite.",
+       "uploaded-wrong-setting-svg": "L’utilisation de la balise « set » pour ajouter à un attribut quelconque une cible distante, de données ou de script est interdite. <code>&lt;set to=\"$1\"&gt;</code> a été trouvé dans le fichier SVG téléversé.",
+       "uploaded-setting-handler-svg": "Les SVG qui positionnent l’attribut « handler » avec distant/données/script sont bloqués. <code>$1=\"$2\"</code> a été trouvé dans le fichier SVG téléversé.",
        "uploaded-remote-url-svg": "Les SVG qui positionnent un attribut de style avec une URL distante sont bloqués. <code>$1=\"$2\"</code> trouvé dans le fichier SVG téléversé.",
        "uploaded-image-filter-svg": "Filtre d’image avec URL trouvé : <code>&lt;$1 $2=\"$3\"&gt;</code> dans le fichier SVG téléversé.",
        "uploadscriptednamespace": "Ce fichier SVG contient un espace de noms '<nowiki>$1</nowiki>' non autorisé.",
        "backend-fail-read": "Impossible de lire le fichier \"$1\".",
        "backend-fail-create": "Impossible d’écrire le fichier « $1 ».",
        "backend-fail-maxsize": "Impossible d’écrire le fichier « $1 » parce qu’il est plus grand {{PLURAL:$2|qu’un octet|que $2 octets}}.",
-       "backend-fail-readonly": "Le support de stockage « $1 » est actuellement en lecture seule. La raison indiquée est : <em>$2</em>",
+       "backend-fail-readonly": "Le support de stockage « $1 » est actuellement en lecture seule. La raison indiquée est : <em>$2</em>",
        "backend-fail-synced": "Le fichier « $1 » est dans un état incohérent dans les supports de stockage internes",
        "backend-fail-connect": "Impossible de se connecter au média de stockage « $1 ».",
        "backend-fail-internal": "Une erreur inconnue s’est produite dans le média de stockage « $1 ».",
        "backend-fail-contenttype": "Impossible de déterminer le type de contenu du fichier à stocker en « $1 ».",
        "backend-fail-batchsize": "On a fourni au support de stockage un lot de $1 {{PLURAL:$1|opération|opérations}} de fichier; la limite est $2 {{PLURAL:$2|opération|opérations}}.",
        "backend-fail-usable": "Impossible de lire ou d’écrire le fichier « $1 » en raison de droits insuffisants ou de répertoires/conteneurs manquants.",
-       "backend-fail-stat": "Impossible de lire l’état du fichier « $1 ».",
-       "backend-fail-hash": "Impossible de déterminer le hachage cryptographique du fichier « $1 ».",
+       "backend-fail-stat": "Impossible de lire l’état du fichier « $1 ».",
+       "backend-fail-hash": "Impossible de déterminer le hachage cryptographique du fichier « $1 ».",
        "filejournal-fail-dbconnect": "Impossible de se connecter à la base de données du journal pour le terminal de stockage « $1 ».",
        "filejournal-fail-dbquery": "Impossible de mettre à jour la base de données du journal pour le terminal de stockage « $1 ».",
        "lockmanager-notlocked": "Impossible de déverrouiller « $1 » ; elle n'est pas verrouillée.",
        "lockmanager-fail-closelock": "Impossible de fermer le fichier de verrou pour « $1 ».",
        "lockmanager-fail-deletelock": "Impossible de supprimer le fichier de verrou pour « $1 ».",
        "lockmanager-fail-acquirelock": "Impossible d'obtenir le verrou pour « $1 ».",
-       "lockmanager-fail-openlock": "Impossible d’ouvrir le fichier de verrou pour « $1 » . Assurez-vous que votre répertoire de téléchargement est configuré correctement et que votre serveur web a le droit d’y écrire. Voyez https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory pour plus d’information.",
+       "lockmanager-fail-openlock": "Impossible d’ouvrir le fichier de verrou pour « $1 » . Assurez-vous que votre répertoire de téléchargement est configuré correctement et que votre serveur web a le droit d’y écrire. Voyez https://www.mediawiki.org/wiki/Special:MyLanguage/Manual:$wgUploadDirectory pour plus d’information.",
        "lockmanager-fail-releaselock": "Impossible de relâcher le verrou pour « $1 ».",
        "lockmanager-fail-db-bucket": "Impossible de contacter suffisamment de bases de données de verrouillage dans le godet $1.",
        "lockmanager-fail-db-release": "Impossible de relâcher les verrous sur la base de données $1.",
        "uploadstash-errclear": "La suppression des fichiers a échoué.",
        "uploadstash-refresh": "Actualiser la liste des fichiers",
        "uploadstash-thumbnail": "afficher la vignette",
-       "uploadstash-exception": "Impossible de stocker le téléversement dans la réserve ($1) : « $2 ».",
+       "uploadstash-exception": "Impossible de stocker le téléversement dans la réserve ($1) : « $2 ».",
        "uploadstash-bad-path": "Le chemin n’existe pas.",
        "uploadstash-bad-path-invalid": "Le chemin n’est pas valide.",
-       "uploadstash-bad-path-unknown-type": "Type « $1 » inconnu.",
+       "uploadstash-bad-path-unknown-type": "Type « $1 » inconnu.",
        "uploadstash-bad-path-unrecognized-thumb-name": "Nom de vignette non reconnu.",
        "uploadstash-bad-path-no-handler": "Aucun gestionnaire trouvé pour le type MIME $1 du fichier $2.",
-       "uploadstash-bad-path-bad-format": "La clé « $1 » n’est pas dans un format correct.",
-       "uploadstash-file-not-found": "La clé « $1 » n’a pas été trouvée dans la réserve.",
+       "uploadstash-bad-path-bad-format": "La clé « $1 » n’est pas dans un format correct.",
+       "uploadstash-file-not-found": "La clé « $1 » n’a pas été trouvée dans la réserve.",
        "uploadstash-file-not-found-no-thumb": "Impossible d’obtenir une vignette.",
        "uploadstash-file-not-found-no-local-path": "Aucun chemin local pour l’élément mis à l’échelle.",
        "uploadstash-file-not-found-no-object": "Impossible de créer l’objet fichier local pour la vignette.",
        "listfiles-delete": "supprimer",
        "listfiles-summary": "Cette page spéciale permet de lister tous les fichiers importés.",
        "listfiles_search_for": "Rechercher un nom de média :",
-       "listfiles-userdoesnotexist": "Le compte utilisateur « $1 » n’est pas enregistré.",
+       "listfiles-userdoesnotexist": "Le compte utilisateur « $1 » n’est pas enregistré.",
        "imgfile": "fichier",
        "listfiles": "Liste de fichiers",
        "listfiles_thumb": "Miniature",
        "randompage": "Page au hasard",
        "randompage-nopages": "Il n'y a aucune page dans {{PLURAL:$2|l'espace de noms|les espaces de noms}} : $1.",
        "randomincategory": "Page au hasard dans la catégorie",
-       "randomincategory-invalidcategory": "« $1 » n’est pas un nom de catégorie valide.",
+       "randomincategory-invalidcategory": "« $1 » n’est pas un nom de catégorie valide.",
        "randomincategory-nopages": "Il n’y a pas de pages dans la catégorie [[:Category:$1|$1]].",
        "randomincategory-category": "Catégorie :",
        "randomincategory-legend": "Page aléatoire dans la catégorie",
        "ancientpages": "Pages les plus anciennement modifiées",
        "move": "Renommer",
        "movethispage": "Renommer cette page",
-       "unusedimagestext": "Les fichiers suivants existent, mais ne sont inclus dans aucune page.\nVeuillez noter que d’autres sites peuvent accéder à ces fichiers à l’aide de liens directs (URLs), et donc qu’un fichier peut être listé ici alors qu’il est utilisé par ces sites.",
+       "unusedimagestext": "Les fichiers suivants existent, mais ne sont inclus dans aucune page.\nVeuillez noter que d’autres sites peuvent accéder à ces fichiers à l’aide de liens directs (URL), et donc qu’un fichier peut être listé ici alors qu’il est utilisé par ces sites.",
        "unusedimagestext-categorizedimgisused": "Les fichiers suivants existent mais ne sont inclus dans aucune page. Les images catégorisées sont considérées comme utilisées malgré qu'elles ne soient pas incluses dans aucune page.\nVeuillez noter que les autres sites web peuvent créer un lien vers un fichier à l'aide d'une URL directe, et donc peuvent encore être listés ici malgré qu'ils soient encore utilisés.",
        "unusedcategoriestext": "Les pages de catégories suivantes existent, mais ne sont utilisées par aucune autre page ni catégorie.",
        "notargettitle": "Pas de cible",
        "suppress": "Supprimer",
        "querypage-disabled": "Cette page spéciale est désactivée pour des raisons de performances.",
        "apihelp": "Aide de l’API",
-       "apihelp-no-such-module": "Le module « $1 » est introuvable.",
+       "apihelp-no-such-module": "Le module « $1 » est introuvable.",
        "apisandbox": "Bac à sable de l'API",
        "apisandbox-jsonly": "Le bac à sable de l'API nécessite JavaScript",
        "apisandbox-intro": "Utilisez cette page pour expérimenter l’<strong>API webservice de MediaWiki</strong>.\nReportez-vous à [[mw:API:Main page|la documentation de l’API]] pour plus de détails sur l’utilisation de l’API. Exemple: [https://www.mediawiki.org/wiki/API#A_simple_example obtenir le contenu d'une page principale]. Choisissez une option pour voir d'autres exemples.",
        "emailccsubject": "Copie de votre message à $1 : $2",
        "emailsent": "Courriel envoyé",
        "emailsenttext": "Votre message a été envoyé par courriel.",
-       "emailuserfooter": "Ce courriel a été {{GENDER:$1|envoyé}} par « $1 » à « {{GENDER:$2|$2}} » par la fonction « {{int:emailuser}} » de {{SITENAME}}. Si {{GENDER:$2|vous}} répondez à ce courriel, {{GENDER:$2|votre}} courriel sera envoyé directement à l’{{GENDER:$1|émetteur initial}}, en {{GENDER:$1|lui}} mentionnant {{GENDER:$2|votre}} adresse courriel .",
+       "emailuserfooter": "Ce courriel a été {{GENDER:$1|envoyé}} par « $1 » à « {{GENDER:$2|$2}} » par la fonction « {{int:emailuser}} » de {{SITENAME}}. Si {{GENDER:$2|vous}} répondez à ce courriel, {{GENDER:$2|votre}} courriel sera envoyé directement à l’{{GENDER:$1|émetteur initial}}, en {{GENDER:$1|lui}} mentionnant {{GENDER:$2|votre}} adresse courriel .",
        "usermessage-summary": "Laisser un message système.",
        "usermessage-editor": "Messager du système",
        "watchlist": "Liste de suivi",
        "watchnologin": "Non connecté",
        "addwatch": "Ajouter à la liste de suivi",
        "addedwatchtext": "La page « [[:$1]] » et sa page de discussion ont été ajoutées à votre [[Special:Watchlist|liste de suivi]].",
-       "addedwatchtext-talk": "« [[:$1]] » et sa page associée ont été ajoutés à votre [[Special:Watchlist|liste de suivi]].",
-       "addedwatchtext-short": "La page « $1 » a été ajoutée à votre liste de suivi.",
+       "addedwatchtext-talk": "« [[:$1]] » et sa page associée ont été ajoutés à votre [[Special:Watchlist|liste de suivi]].",
+       "addedwatchtext-short": "La page « $1 » a été ajoutée à votre liste de suivi.",
        "removewatch": "Supprimer de la liste de suivi",
-       "removedwatchtext": "La page « [[:$1]] » et sa page de discussion ont été retirées de votre [[Special:Watchlist|liste de suivi]].",
-       "removedwatchtext-talk": "« [[:$1]] » et sa page associée ont été supprimés de votre [[Special:Watchlist|liste de suivi]].",
-       "removedwatchtext-short": "La page « $1 » a été supprimée de votre liste de suivi.",
+       "removedwatchtext": "La page « [[:$1]] » et sa page de discussion ont été retirées de votre [[Special:Watchlist|liste de suivi]].",
+       "removedwatchtext-talk": "« [[:$1]] » et sa page associée ont été supprimés de votre [[Special:Watchlist|liste de suivi]].",
+       "removedwatchtext-short": "La page « $1 » a été supprimée de votre liste de suivi.",
        "watch": "Suivre",
        "watchthispage": "Suivre cette page",
        "unwatch": "Ne plus suivre",
        "alreadyrolled": "Impossible de révoquer la dernière modification de la page « [[:$1]] » effectuée par [[User:$2|$2]] ([[User talk:$2|Discuter]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) ;\nquelqu'un d'autre a déjà modifié ou révoqué la page.\n\nLa dernière modification de la page a été effectuée par [[User:$3|$3]] ([[User talk:$3|Discuter]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Le résumé de la modification était : <em>$1</em>.",
        "revertpage": "Révocation des modifications de [[Special:Contributions/$2|$2]] ([[User talk:$2|discussion]]) vers la dernière version de [[User:$1|$1]]",
+       "revertpage-anon": "Modifications de [[Special:Contributions/$2|$2]] révoquées vers la dernière version de [[User:$1|$1]]",
        "revertpage-nouser": "Révocation des modifications par un utilisateur masqué à la dernière version par {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Révocation des modifications effectuées par {{GENDER:$3|$1}} ;\nrétablissement de la dernière version par {{GENDER:$4|$2}}.",
        "sessionfailure-title": "Erreur de session",
        "changecontentmodel-emptymodels-text": "Le contenu sur [[:$1]] ne peut être converti en aucun type.",
        "log-name-contentmodel": "Journal de modification de modèle de contenu",
        "log-description-contentmodel": "Cette page montre des modifications dans le modèle de contenu des pages, ainsi que les pages créées avec un modèle de contenu différent du contenu par défaut.",
-       "logentry-contentmodel-new": "$1 {{GENDER:$2|a créé}} la page $3 en utilisant un modèle de contenu « $5 » autre que celui par défaut",
-       "logentry-contentmodel-change": "$1 {{GENDER:$2|a modifié}} le modèle de contenu de la page $3 de « $4 » en « $5 »",
+       "logentry-contentmodel-new": "$1 {{GENDER:$2|a créé}} la page $3 en utilisant un modèle de contenu « $5 » autre que celui par défaut",
+       "logentry-contentmodel-change": "$1 {{GENDER:$2|a modifié}} le modèle de contenu de la page $3 de « $4 » en « $5 »",
        "logentry-contentmodel-change-revertlink": "rétablir",
        "logentry-contentmodel-change-revert": "rétablir",
        "protectlogpage": "Journal des protections",
        "unprotectedarticle": "a supprimé la protection de « [[$1]] »",
        "movedarticleprotection": "a déplacé les paramètres de protection depuis « [[$2]] » vers « [[$1]] »",
        "protectedarticle-comment": "{{GENDER:$2|A protégé}} « [[$1]] »",
-       "modifiedarticleprotection-comment": "{{GENDER:$2|A changé le niveau de protection}} pour « [[$1]] »",
-       "unprotectedarticle-comment": "{{GENDER:$2|A supprimé la protection}} de « [[$1]] »",
+       "modifiedarticleprotection-comment": "{{GENDER:$2|A changé le niveau de protection}} pour « [[$1]] »",
+       "unprotectedarticle-comment": "{{GENDER:$2|A supprimé la protection}} de « [[$1]] »",
        "protect-title": "Changer le niveau de protection pour « $1 »",
        "protect-title-notallowed": "Voir le niveau de protection de « $1 »",
        "prot_1movedto2": "[[$1]] renommé en [[$2]]",
        "anoncontribs": "Contributions",
        "contribsub2": "Pour {{GENDER:$3|$1}} ($2)",
        "contributions-subtitle": "Pour {{GENDER:$3|$1}}",
-       "contributions-userdoesnotexist": "Le compte d’utilisateur « $1 » n’est pas enregistré.",
+       "contributions-userdoesnotexist": "Le compte d’utilisateur « $1 » n’est pas enregistré.",
        "negative-namespace-not-supported": "Les espaces de noms avec des valeurs négatives ne sont pas supportés.",
        "nocontribs": "Aucune modification correspondant à ces critères n'a été trouvée.",
        "uctop": "actuelle",
        "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.",
+       "ipb-confirmaction": "Si vous êtes sûr{{GENDER:||e}} de vraiment vouloir le faire, veuillez cocher le champ « {{int:ipb-confirm}} » en bas.",
        "ipb-edit-dropdown": "Modifier les motifs de blocage par défaut",
        "ipb-unblock-addr": "Débloquer $1",
        "ipb-unblock": "Débloquer un compte utilisateur ou une adresse IP",
        "ipblocklist-legend": "Chercher un utilisateur bloqué",
        "blocklist-userblocks": "Masquer les blocages de comptes",
        "blocklist-tempblocks": "Masquer les blocages temporaires",
+       "blocklist-indefblocks": "Masquer les blocs non définis",
        "blocklist-addressblocks": "Masquer les blocages d’adresses IP uniques",
        "blocklist-type": "Type :",
        "blocklist-type-opt-all": "Tous",
        "empty-username": "(aucun nom d’utilisateur disponible)",
        "contribslink": "contributions",
        "emaillink": "envoyer un courriel",
-       "autoblocker": "Vous avez été bloqué automatiquement parce que votre adresse IP a été récemment utilisée par « [[User:$1|$1]] ».\nLe motif fourni pour le blocage de $1 est « $2 »",
+       "autoblocker": "Vous avez été bloqué automatiquement parce que votre adresse IP a été récemment utilisée par « [[User:$1|$1]] ».\nLe motif fourni pour le blocage de $1 est « $2 »",
        "blocklogpage": "Journal des blocages",
        "blocklog-showlog": "Cet utilisateur a été bloqué précédemment. \nLe journal des blocages est affiché ci-dessous pour référence :",
        "blocklog-showsuppresslog": "Cet utilisateur a été bloqué et masqué précédemment. \nLe journal des masquages est affiché ci-dessous pour référence :",
        "cant-move-category-page": "Vous n'avez pas la permission de renommer les pages de catégorie.",
        "cant-move-to-category-page": "Vous n'avez pas la permission de renommer une page vers une page de catégorie.",
        "cant-move-subpages": "Vous n’avez pas le droit de renommer des sous-pages.",
-       "namespace-nosubpages": "L’espace de noms « $1 » n’autorise pas les sous-pages.",
+       "namespace-nosubpages": "L’espace de noms « $1 » n’autorise pas les sous-pages.",
        "newtitle": "Nouveau titre :",
        "move-watch": "Suivre les pages originale et nouvelle",
        "movepagebtn": "Renommer la page",
        "movenosubpage": "Cette page n'a aucune sous-page.",
        "movereason": "Motif :",
        "revertmove": "rétablir",
-       "delete_and_move_text": "La page de destination « [[:$1]] » existe déjà.\nÊtes-vous certain{{GENDER:||e|}} de vouloir la supprimer pour permettre ce renommage ?",
+       "delete_and_move_text": "La page de destination « [[:$1]] » existe déjà.\nÊtes-vous certain{{GENDER:||e|}} de vouloir la supprimer pour permettre ce renommage ?",
        "delete_and_move_confirm": "Oui, supprimer la page de destination",
        "delete_and_move_reason": "Page supprimée pour permettre le renommage depuis « [[$1]] »",
        "selfmove": "Le titre est le même ;\nimpossible de renommer une page sur elle-même.",
        "import-upload": "Import de données XML",
        "import-token-mismatch": "Perte des données de session.\n\nVous avez peut-être été déconnecté. '''Veuillez vérifier que vous êtes toujours connecté et réessayez'''.\nSi cela ne fonctionne toujours pas, essayez de [[Special:UserLogout|vous déconnecter]] et de vous reconnecter, et vérifiez que votre navigateur accepte les témoins (''cookies'') de ce site.",
        "import-invalid-interwiki": "Impossible d'importer depuis le wiki spécifié.",
-       "import-error-edit": "La page « $1 » n’a pas été importée parce que vous n’êtes pas autorisé à la modifier.",
-       "import-error-create": "La page « $1 » n’a pas été importée parce que vous n’êtes pas autorisé à la créer.",
-       "import-error-interwiki": "La page « $1 » n’a pas été importée parce que son nom est réservé pour un lien externe (interwiki).",
-       "import-error-special": "La page « $1 » n’a pas été importée parce qu’elle appartient à un espace de noms spécial qui n’autorise aucune page.",
-       "import-error-invalid": "Page « $1 » n’a pas été importée parce que le nom sous lequel elle aurait été importée n’est pas valide sur ce wiki.",
+       "import-error-edit": "La page « $1 » n’a pas été importée parce que vous n’êtes pas autorisé à la modifier.",
+       "import-error-create": "La page « $1 » n’a pas été importée parce que vous n’êtes pas autorisé à la créer.",
+       "import-error-interwiki": "La page « $1 » n’a pas été importée parce que son nom est réservé pour un lien externe (interwiki).",
+       "import-error-special": "La page « $1 » n’a pas été importée parce qu’elle appartient à un espace de noms spécial qui n’autorise aucune page.",
+       "import-error-invalid": "Page « $1 » n’a pas été importée parce que le nom sous lequel elle aurait été importée n’est pas valide sur ce wiki.",
        "import-error-unserialize": "La révision $2 de la page « $1 » ne peut pas être désérialisée. La révision est indiquée comme utilisant le modèle de contenu $3 sérialisé en $4.",
-       "import-error-bad-location": "La révision $2 utilisant le modèle de contenu $3 n’a pas pu être stockée sur « $1 » sur ce wiki, car ce modèle n’est pas pris en charge sur cette page.",
+       "import-error-bad-location": "La révision $2 utilisant le modèle de contenu $3 n’a pas pu être stockée sur « $1 » sur ce wiki, car ce modèle n’est pas pris en charge sur cette page.",
        "import-options-wrong": "{{PLURAL:$2|Mauvaise option|Mauvaises options}} : <nowiki>$1</nowiki>",
        "import-rootpage-invalid": "La page racine fournie est un titre non valide.",
        "import-rootpage-nosubpage": "L'espace de noms « $1 » de la page racine n'autorise pas les sous-pages.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|révision importée|révisions importées}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|révision importée|révisions importées}} depuis $2",
        "javascripttest": "Test de JavaScript",
-       "javascripttest-pagetext-unknownaction": "Action « $1 » inconnue.",
+       "javascripttest-pagetext-unknownaction": "Action « $1 » inconnue.",
        "javascripttest-qunit-intro": "Voir [$1 la documentation de test] sur mediawiki.org.",
        "tooltip-pt-userpage": "Votre page d’{{GENDER:|utilisateur|utilisatrice}}",
        "tooltip-pt-anonuserpage": "La page utilisateur avec l'adresse IP de laquelle vous contribuez",
        "confirmemail_subject": "Confirmation d’adresse de courriel pour {{SITENAME}}",
        "confirmemail_body": "Quelqu’un, probablement vous, à partir de l’adresse IP $1,\na créé un compte « $2 » avec cette adresse de courriel sur le site {{SITENAME}}.\n\nPour confirmer que ce compte vous appartient vraiment et afin\nd’activer les fonctions de messagerie sur {{SITENAME}},\nveuillez suivre ce lien dans votre navigateur :\n\n$3\n\nSi vous n’avez *pas* créé ce compte, suivez le lien ci-dessous \npour annuler la confirmation de votre adresse courriel :\n\n$5\n\nCe code de confirmation expirera le $4.",
        "confirmemail_body_changed": "Quelqu’un, probablement vous, à partir de l’adresse IP $1,\na modifié l’adresse de courriel associée au compte « $2 » de {{SITENAME}}\nen cette adresse.\n\nPour confirmer que ce compte vous appartient vraiment et afin\nde réactiver les fonctions de messagerie sur {{SITENAME}},\nveuillez suivre ce lien dans votre navigateur :\n\n$3\n\nSi ce compte ne vous appartient *pas*, n’ouvrez pas ce lien ;\nvous pouvez suivre l’autre lien ci-dessous pour annuler la\nconfirmation de votre adresse courriel :\n\n$5\n\nCe code de confirmation expirera le $4.",
-       "confirmemail_body_set": "Quelqu’un, probablement vous, depuis l’adresse IP $1, a modifié l’adresse de courriel du compte « $2 » en celle-ci sur {{SITENAME}}.\n\nPour confirmer que ce compte vous appartient et réactiver les fonctions de courriel sur {{SITENAME}}, ouvrez ce lien dans votre navigateur Web :\n\n$3\n\nSi le compte ne vous appartient *pas*, suivez plutôt ce lien pour annuler la confirmation de l’adresse de courriel :\n\n$5\n\nCe code de confirmation expirera le $4.",
+       "confirmemail_body_set": "Quelqu’un, probablement vous, depuis l’adresse IP $1, a modifié l’adresse de courriel du compte « $2 » en celle-ci sur {{SITENAME}}.\n\nPour confirmer que ce compte vous appartient et réactiver les fonctions de courriel sur {{SITENAME}}, ouvrez ce lien dans votre navigateur Web :\n\n$3\n\nSi le compte ne vous appartient *pas*, suivez plutôt ce lien pour annuler la confirmation de l’adresse de courriel :\n\n$5\n\nCe code de confirmation expirera le $4.",
        "confirmemail_invalidated": "Confirmation de l’adresse courriel annulée",
        "invalidateemail": "Annuler la confirmation de l'adresse de courriel",
        "notificationemail_subject_changed": "L’adresse courriel enregistrée sur {{SITENAME}} a été changée",
        "parentheses-start": "(",
        "parentheses-end": ")",
        "brackets": "[$1]",
-       "quotation-marks": "« $1 »",
+       "quotation-marks": "« $1 »",
        "imgmultipageprev": "← page précédente",
        "imgmultipagenext": "page suivante →",
        "imgmultigo": "Accéder !",
        "tags-deactivate-submit": "Désactiver",
        "tags-apply-no-permission": "Vous n’avez pas le droit d’appliquer des balises de changement en même temps que vos modifications.",
        "tags-apply-blocked": "Vous ne pouvez pas appliquer les modifications de balises et vos modifications lorsque vous êtes bloqué{{GENDER:$1||e}}.",
-       "tags-apply-not-allowed-one": "La balise « $1 » n’est pas autorisée à être appliquée manuellement.",
+       "tags-apply-not-allowed-one": "La balise « $1 » n’est pas autorisée à être appliquée manuellement.",
        "tags-apply-not-allowed-multi": "{{PLURAL:$2|La balise suivante n’est pas autorisée à être appliquée|Les balises suivantes ne sont pas autorisées à être appliquées}} manuellement : $1",
        "tags-update-no-permission": "Vous n’avez pas le droit d’ajouter ou de supprimer \nles balises de modification des révisions individuelles ou des entrées de journal.",
        "tags-update-blocked": "Vous ne pouvez pas ajouter ou supprimer des balises de modifications lorsque vous êtes bloqué{{GENDER:$1||e}}.",
-       "tags-update-add-not-allowed-one": "La balise « $1 » ne peut pas être ajoutée manuellement.",
+       "tags-update-add-not-allowed-one": "La balise « $1 » ne peut pas être ajoutée manuellement.",
        "tags-update-add-not-allowed-multi": "{{PLURAL:$2|La balise suivante ne peut pas être ajoutée|Les balises suivantes ne peuvent pas être ajoutées}} manuellement : $1",
-       "tags-update-remove-not-allowed-one": "La balise « $1 » ne peut pas être enlevée.",
+       "tags-update-remove-not-allowed-one": "La balise « $1 » ne peut pas être enlevée.",
        "tags-update-remove-not-allowed-multi": "{{PLURAL:$2|La balise suivante ne peut pas être enlevée|Les balises suivantes ne peuvent pas être enlevées}} manuellement : $1",
        "tags-edit-title": "Modifier les balises",
        "tags-edit-manage-link": "Gérer les balises",
        "logentry-upload-revert": "$1 {{GENDER:$2|a annulé}} $3 vers une ancienne version",
        "log-name-managetags": "Journal des modifications de balises",
        "log-description-managetags": "Cette page recense les tâches de maintenance liées aux [[Special:Tags|balises]]. Le journal contient uniquement les actions faites manuellement par un administrateur ; les balises peuvent être créées ou supprimées par le logiciel wiki sans que cette action ne soit inscrite dans ce journal.",
-       "logentry-managetags-create": "$1 {{GENDER:$2|a créé}} la balise « $4 ».",
-       "logentry-managetags-delete": "$1 {{GENDER:$2|a supprimé}} la balise « $4 » (retirée {{PLURAL:$5|d'une révision ou entrée de journal|de $5 révisions ou entrées de journal}})",
-       "logentry-managetags-activate": "$1 {{GENDER:$2|a activé}} la balise « $4 » pour l’usage des utilisateurs et des robots",
-       "logentry-managetags-deactivate": "$1 {{GENDER:$2|a désactivé}} la balise « $4 » pour l’usage des utilisateurs et des robots",
+       "logentry-managetags-create": "$1 {{GENDER:$2|a créé}} la balise « $4 ».",
+       "logentry-managetags-delete": "$1 {{GENDER:$2|a supprimé}} la balise « $4 » (retirée {{PLURAL:$5|d'une révision ou entrée de journal|de $5 révisions ou entrées de journal}})",
+       "logentry-managetags-activate": "$1 {{GENDER:$2|a activé}} la balise « $4 » pour l’usage des utilisateurs et des robots",
+       "logentry-managetags-deactivate": "$1 {{GENDER:$2|a désactivé}} la balise « $4 » pour l’usage des utilisateurs et des robots",
        "log-name-tag": "Journal des balises",
        "log-description-tag": "Cette page montre quand des utilisateurs ont ajouté ou supprimé des [[Special:Tags|balises]] de révisions individuelles ou d’entrées de journal. Le journal ne liste pas les actions de marquage quand elles ont lieu au cours d’une modification, d’une suppression, ou d’une action semblable.",
        "logentry-tag-update-add-revision": "$1 {{GENDER:$2|a ajouté}} {{PLURAL:$7|la balise|les balises}} $6 à la révision $4 de la page $3",
        "api-error-emptypage": "Création de pages vide n'est pas autorisée.",
        "api-error-publishfailed": "Erreur interne : Le serveur n'a pas pu publier le fichier temporaire.",
        "api-error-stashfailed": "Erreur interne : le serveur n'a pas pu enregistrer le fichier temporaire.",
-       "api-error-unknown-warning": "Avertissement inconnu : « $1 ».",
+       "api-error-unknown-warning": "Avertissement inconnu : « $1 ».",
        "api-error-unknownerror": "Erreur inconnue : « $1 ».",
        "duration-seconds": "$1 seconde{{PLURAL:$1||s}}",
        "duration-minutes": "$1 minute{{PLURAL:$1||s}}",
        "authmanager-link-not-in-progress": "La liaison de compte n’est pas en cours ou les données de session ont été perdues. Veuillez recommencer depuis le début.",
        "authmanager-autocreate-noperm": "La création automatique de compte n’est pas autorisée.",
        "authmanager-autocreate-exception": "La création automatique de compte est désactivée temporairement, du fait d’erreurs antérieures.",
-       "authmanager-userdoesnotexist": "Le compte utilisateur « $1 » n’est pas inscrit.",
+       "authmanager-userdoesnotexist": "Le compte utilisateur « $1 » n’est pas inscrit.",
        "authmanager-userlogin-remembermypassword-help": "Indique si le mot de passe doit être mémorisé au-delà de la durée de la session.",
        "authmanager-username-help": "Nom d’utilisateur pour l’authentification.",
        "authmanager-password-help": "Mot de passe pour l’authentification.",
        "authprovider-confirmlink-ok-help": "Continuer après l’affichage des messages d’échec de liaison.",
        "authprovider-resetpass-skip-label": "Sauter",
        "authprovider-resetpass-skip-help": "Sauter la réinitialisation du mot de passe.",
-       "authform-nosession-login": "L’authentification a réussi, mais votre navigateur ne peut pas se « souvenir » d’avoir été connecté.\n\n$1",
-       "authform-nosession-signup": "Le compte a été créé, mais votre navigateur ne peut pas se « souvenir » avoir été connecté.\n\n$1",
+       "authform-nosession-login": "L’authentification a réussi, mais votre navigateur ne peut pas se « souvenir » d’avoir été connecté.\n\n$1",
+       "authform-nosession-signup": "Le compte a été créé, mais votre navigateur ne peut pas se « souvenir » avoir été connecté.\n\n$1",
        "authform-newtoken": "Jeton manquant. $1",
        "authform-notoken": "Jeton manquant",
        "authform-wrongtoken": "Mauvais jeton",
index d8dffa5..38139ab 100644 (file)
        "systemblockedtext": "O seu nome de usuario ou enderezo IP foi bloqueado automaticamente polo sistema MediaWiki.\nO motivo do bloqueo é:\n\n:<em>$2</em>\n\n* Comezo do bloqueo: $8\n* Expiración do bloqueo: $6\n* Destinatario do bloqueo: $7\n\nO seu enderezo IP actual é $3.\nPor favor, inclúa todos estes detalles en calquera consulta que realice.",
        "blockednoreason": "non se deu ningunha razón",
        "blockedtext-composite": "<strong>O seu nome de usuario ou enderezo IP foron bloqueados.</strong>\n\nO motivo dado é:\n\n:<em>$2</em>.\n\n* Comezo do bloqueo: $8\n* Remate do bloqueo máis longo: $6\n\n* $5\n\nO seu enderezo IP actual é $3.\nPor favor, inclúa todos os detalles de arriba en calquera contacto sobre este asunto.",
+       "blockedtext-composite-ids": "Identificadores de bloqueo relevantes: $1 (o seu enderezo IP pode atoparse tamén nalgunha lista negra)",
        "blockedtext-composite-no-ids": "O seu enderezo IP aparece en múltiples listas negras",
        "blockedtext-composite-reason": "Existen varios bloqueos contra a súa conta ou enderezo IP",
        "whitelistedittext": "Debe $1 para poder editar páxinas.",
        "nocreate-loggedin": "Non ten os permisos necesarios para crear páxinas novas.",
        "sectioneditnotsupported-title": "A edición de seccións non está soportada",
        "sectioneditnotsupported-text": "A edición de seccións non está soportada nesta páxina.",
+       "modeleditnotsupported-title": "Non se permite a edición",
        "permissionserrors": "Erro de permisos",
        "permissionserrorstext": "Non ten os permisos necesarios para facelo {{PLURAL:$1|pola seguinte razón|polas seguintes razóns}}:",
        "permissionserrorstext-withaction": "Non ten os permisos necesarios para $2, {{PLURAL:$1|pola seguinte razón|polas seguintes razóns}}:",
index 9c5a899..9a45be1 100644 (file)
        "tog-previewonfirst": "पयल्याच संपादनाचेर पुर्वनियाळ दाखय",
        "tog-enotifwatchlistpages": "म्हज्या सादुरवळेरेंतलें पान वा फायल बदल्ली जाल्यार म्हाका इमेल करात",
        "tog-shownumberswatching": "ध्यान दवरपी वांगड्यांची संख्या दाखय",
-       "tog-oldsig": "सद्याची निशाणी",
-       "tog-uselivepreview": "लायव à¤ªà¥\81रà¥\8dवनियाळाà¤\9aà¥\8b à¤µà¤¾à¤ªà¤°",
+       "tog-oldsig": "तà¥\81à¤\9cà¥\8dया à¤¸à¤§्याची निशाणी",
+       "tog-uselivepreview": "पान à¤ªà¤°à¤¤ à¤\89à¤\97डनासताना à¤\9dलà¤\95 à¤¦à¤¾à¤\96य",
        "tog-watchlisthideown": "सादुरवळेरीतलें म्हजे संपादन लिपय",
        "tog-watchlisthidebots": "ध्यानसुचीतले रोबोट संपादन लिपय",
        "tog-watchlisthideminor": "सादुरवळेरीतले ल्हान संपादन लिपय",
        "tog-showhiddencats": "लिपोवन दवरिल्ले विभाग दाखय",
        "underline-always": "सदा (केधन्नय) (केन्नय)",
        "underline-never": "केधन्नयना (केन्नना)",
-       "underline-default": "बà¥\8dराà¤\89à¤\9c़र à¤¡à¤¿à¤«à¤¼à¥\89लà¥\8dà¤\9f",
+       "underline-default": "सà¥\8dà¤\95à¥\80न à¤µà¤¾ à¤¬à¥\8dरावसरा à¤ªà¥\8dरमाणà¥\87à¤\82",
        "sunday": "आयतार",
        "monday": "सोमार",
        "tuesday": "मंगळार",
        "category_header": "\"$1\" ह्या वर्गातलीं पानां",
        "subcategories": "उपवर्ग",
        "category-media-header": "\"$1\" वर्गातलें प्रसार माध्यम",
+       "category-empty": "<em>ह्या वर्गान सध्या एकूय पान वा माध्यम ना.</em>",
        "hidden-categories": "{{PLURAL:$1|लिपिल्लें वर्ग|लिपिल्लें वर्ग }}",
        "hidden-category-category": "लिपयिल्ले विभाग",
        "category-subcat-count": "{{PLURAL:$2|ह्या वर्गान फकत सकयल दिल्ले उपविभाग आसात.|ह्या वर्गातल्या $2 वट्ट {{PLURAL:$1|सकयल दिल्ले उपवर्ग आसात.|$1सकयल दिल्ले उपवर्ग आसात.}}}}",
        "category-article-count": "{{PLURAL:$2|ह्या वर्गांत सकयल दिल्लीं पानां आसात.|ह्या वर्गांत सकलय दिल्लीं {{PLURAL:$1|पानां आसात|$1 पानां आसात}}, वट्ट पानां $2}}",
        "category-file-count": "{{PLURAL:$2|ह्या वर्गांत फकत सकयली फायल आसपावता.|ह्या वर्गांत सकयल दिल्लीं {{PLURAL:$1|फायल|$1 फायलीं}} आसता, वट्ट फायलीं $2}}",
        "listingcontinuesabbrev": "चालू.",
-       "noindex-category": "बिननिर्देशांकी पानां",
+       "noindex-category": "सुचीपत्रान जोडूंक-नासलेलीं पानां",
+       "broken-file-category": "तुटलेल्या फायलींचो दुवे आसलेलीं पानां",
        "about": "विशीं",
        "article": "मजकूराचीं पानां",
        "newwindow": "(नव्या ज़ोणेलांत उकतें जाता)",
        "cancel": "रद्द करात",
        "moredotdotdot": "आनीक",
-       "morenotlisted": "हà¥\80 à¤¸à¥\82à¤\9aà¥\80 à¤ªà¥\82रà¥\8dण à¤¨à¤¾",
+       "morenotlisted": "हà¥\80 à¤¸à¥\81à¤\9aà¥\80 à¤ªà¥\82रà¥\8dण à¤¨à¤¾à¤¸à¥\82à¤\82à¤\95 à¤¶à¤\95à¥\8dता.",
        "mypage": "पान",
        "mytalk": "चर्चा",
        "navigation": "दिशा-नियंत्रण",
        "redirectedfrom": "($1 सून पुनर्निर्देशित)",
        "redirectpagesub": "पान परतून निर्देशीत करचें",
        "redirectto": "हांगां पुनर्निर्देशित:",
-       "lastmodifiedat": "हà¥\8dया à¤ªà¤¾à¤¨à¤¾à¤\82त à¤¨à¤¿à¤®à¤¾à¤£à¥\8b à¤¬à¤¦à¤²,$1 à¤µà¥\87र $2 à¤µà¥\87ळार à¤\95à¥\87लà¥\8dलà¥\8b",
+       "lastmodifiedat": "हà¥\87à¤\82 à¤ªà¤¾à¤¨ à¤¶à¥\87वà¤\9fà¥\80à¤\82 $1 à¤¦à¤¿à¤¸à¤¾, $2 à¤µà¥\8bराà¤\82à¤\9aà¥\8bर à¤¬à¤¦à¤²à¥\87लà¥\87à¤\82.",
        "protectedpage": "राखून दवरिल्लें पान",
        "jumpto": "हुपून वचात:",
        "jumptonavigation": "दिशा-नियंत्रण",
        "privacypage": "Project:गुप्ततायेचें धोरण",
        "ok": "बरें",
        "retrievedfrom": "\"$1\" चे कडल्यान परतून मेळयलें",
+       "youhavenewmessages": "{{PLURAL:$3|तुमकां}} $1 ($2) आसात.",
+       "youhavenewmessagesfromusers": "तुका {{PLURAL:$3एक वापरपी|$3 वापरपी}} कडल्यान $1 {{PLURAL:$4|आसा|आसात}} ($2).‎",
+       "newmessageslinkplural": "{{PLURAL:$1|नवो संदेश|999=नवे संदेश}}‎",
+       "newmessagesdifflinkplural": "{{PLURAL:$1|निमाणो बदल|999=निमाणे बदल}}",
        "youhavenewmessagesmulti": "$1 चेर तुका नवो संदेश आसा",
        "editsection": "बदल",
        "editold": "बदल",
        "collapsible-expand": "विस्तार",
        "confirmable-yes": "हय",
        "confirmable-no": "ना",
-       "thisisdeleted": "पळय आनी परतून हाड 1?",
+       "thisisdeleted": "$1 पळय वा परत हाड?",
        "viewdeleted": "दाखयात $1?",
        "feedlinks": "पुरवय :",
        "feed-invalid": "चुकीचें सब्सक्रिप्शन फीड प्रकार",
        "mainpage-nstab": "मुखेल पान",
        "nosuchaction": "असले तरेचे कार्य ना",
        "nosuchspecialpage": "असले कांयच विशेश पान ना",
+       "nospecialpagetext": "<strong>तुवें एक अवैद खेरीत पान मागलां.</strong>\n\nएक खेरीत पानाची वळेरी तुका हांगासर मेळूं येता [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "चूक",
        "databaseerror": "डॅटाबॅज त्रुटी",
        "databaseerror-textcl": "डॅटाबेज विरोध त्रुटी आयिल्ली आसा",
        "databaseerror-query": "अनुरोध: $1",
        "databaseerror-error": "चूक: $1",
-       "missing-article": "डेटाबेजाक \"$1\" $2 ह्या नांवाचें जे मजकूराचें पान मेळूंक जाय आसलें तें मेळ्ळेंना. हें चड करून जेन्ना काडून उडयिल्ल्या पानाक मुजत सोंपिळ्ळे डिफ वा इतिहासाचो दुवो दिवप जाता तेन्ना घडटा..जर अशें नासत तर तुमकां सॉफ्टवेरांत चूक सांपडूंक जाय हें अँडमिनिस्ट्रेटराक URLची नोंद करून कळयात.",
+       "missing-article": "डेटाबेजाक \"$1\" $2 ह्या नांवाचें जे मजकूराचें पान मेळूंक जाय आसलें तें मेळ्ळेंना. हें चड करून जेन्ना काडून उडयिल्ल्या पानाक मुजत सोंपिळ्ळे डिफ वा इतिहासाचो दुवो दिवप जाता तेन्ना घडटा..जर अशें नासत तर तुमकां सॉफ्टवेरांत चूक सांपडूंक जाय हें अँडमिनिस्ट्रेटराक URLची नोंद करून कळयात.\n\n\nम्हायतीकोश (Database) हांतूत मेळूंक जाय आसलें तें मजकूर \"$1\" $2 मेळूंक नां.\n\nहरर्शीं, अशें एक पोरणें एक फरक वा एका पानाच्या इतिहासाचो दुवो काडून उडयला, तेन्ना जाता.\n\nअशें न्हय जाल्यार, तुका सोफ्टवेरान चूक सांपडलेया जायत.\nउपकार करून एका [[Special:ListUsers/sysop|कार्भारीच्या]] नतरेक हाड, अतरजाळ्यांत जागो सोदपी (यु. आर. एल.) हाची नोंद घेवन.",
        "missingarticle-rev": "पुनर्नियाळ $1",
        "badtitle": "चुकीचो माथाळो",
        "badtitletext": "विनवणी केल्लें पानाचो माथाळो अवैध, रितो वा अयोग्य तरेन आंतरभाशी वा आंतर विकी माथाळ्या कडे जोडिल्लो आशिल्लो. तातूंत माथाळ्यांत वापरुं नजो अशी एक वा चड अक्षरां आसूं येतात.",
        "viewsource": "उगम पळेयात",
+       "viewsource-title": "$1‎ खातीर मूळ पळय",
+       "viewsourcetext": "तुज्यान ह्या पानाचें मूळ पळोवंक आनी नकल करुंक जाता.",
        "yourname": "वापरप्याचे नांव",
        "userlogin-yourname": "वापरप्याचे नांव",
        "userlogin-yourname-ph": "वापरप्याचे नांव घालात",
        "loginerror": "लॉन इन त्रुटी",
        "createacct-error": "खातें निर्माण त्रुटी",
        "createaccounterror": "खातें तयार करूंक जायना: $1",
-       "loginsuccesstitle": "लà¥\89न à¤\87न à¤¯à¤¶à¤¸à¥\8dवà¥\80 à¤\9cालां",
+       "loginsuccesstitle": "सतà¥\8dरारà¤\82भ à¤\9cालà¥\87ं",
        "nosuchusershort": "\"$1\" ह्या नांवान कोण वापरपी ना.\nउतरां तपासून पळय",
        "nouserspecified": "वापरप्याचें नांव तुवें सांगूंक जाय",
        "login-userblocked": "ह्या वापरप्याक बंद केला. लॉग इन करूंक जायना.",
-       "wrongpassword": "à¤\9aà¥\81à¤\95िà¤\9aà¥\87à¤\82 à¤\97à¥\81पà¥\80त à¤\89तर à¤\98ातलाà¤\82.\nà¤\89पà¤\95ार à¤\95रà¥\82न à¤ªà¤°à¤¤à¥\82न यत्न कर.",
+       "wrongpassword": "à¤\9aà¥\81à¤\95à¥\80à¤\9aà¥\87à¤\82 à¤µà¤¾à¤ªà¤°à¤ªà¥\8dयाà¤\9aà¥\87à¤\82 à¤¨à¤¾à¤\82व à¤µà¤¾ à¤\97à¥\81पà¥\80तà¤\89तर à¤\98ातलाà¤\82.\nà¤\89पà¤\95ार à¤\95रà¥\82न à¤ªà¤°à¤¤à¥\82न à¤ªà¥\8dरयत्न कर.",
        "wrongpasswordempty": "गुपीत उतर घालूंक ना.\nउपकार करून परतून यत्न कर.",
        "passwordtoolong": "गुपीत उतर हाच्या परस चड व्हड आसूंक फावना{{PLURAL:$1|1 वर्ण|$1 वर्णां}}.",
        "password-name-match": "तुजें गुपीत उतर वापरप्याच्या नांवा परस वेगळें आसूंक जाय.",
        "emaildisabled": "ही साइट मेल धाडपाक शकना.",
        "accountcreated": "खातें तयाओर केलें",
        "createaccount-title": "{{SITENAME}} हाका लागून खातें तयार केलां",
-       "login-abort-generic": "तà¥\81मà¤\9aà¥\87à¤\82 à¤²à¥\89à¤\97 à¤\87न à¤\85पà¥\87शà¥\80 à¤¥à¤¾à¤°à¤²à¤¾à¤\82 - à¤¨à¤¿à¤¶à¥\8dफलीत",
+       "login-abort-generic": "तà¥\81à¤\9cà¥\87à¤\82 à¤¸à¤¤à¥\8dरारà¤\82भ à¤\85पà¥\87शà¥\80 à¤¥à¤¾à¤°à¤²à¤¾à¤\82 â\80\93 à¤¨à¤¿à¤¶à¤«à¤³ीत",
        "login-migrated-generic": "तुमचें खातें स्थलांतरीत जालां आनी तुजें वापरप्याचें नांव ह्या विकीचेर उपस्थीत ना.",
        "loginlanguagelabel": "भास:$1",
        "pt-login": "सत्रारंभ",
        "newpassword": "नवें गुपीत उतर",
        "retypenew": "नवें गुपीत उतर परतून टाइप कर",
        "resetpass_submit": "गुपीत उतर तयार कर आनी लॉग इन कर",
-       "changepassword-success": "तुजें गुपीत उतर बदलप यशस्वी थारलां",
+       "changepassword-success": "तुजें गुपीतउतर बदल्लां!",
        "resetpass_forbidden": "गुपीत उतरां बदलूंक शकनात",
        "resetpass-submit-loggedin": "गुपीत उतर बदलात",
        "resetpass-submit-cancel": "रद्द करात",
        "passwordreset-domain": "डोमेन:",
        "passwordreset-email": "ईमेल नामो:",
        "passwordreset-emailelement": "वापरप्याचें नांव: \n$1\n\nतात्पुरतें गुपीत उतर: \n$2",
-       "passwordreset-emailsentemail": "à¤\97à¥\81पà¥\80त à¤\89तर à¤ªà¤°à¤¤à¥\82न à¤¤à¤¯à¤¾à¤° à¤\95रपाà¤\9aà¥\8b à¤\88मà¥\87ल à¤§à¤¾à¤¡à¤²à¤¾",
-       "changeemail": "à¤\88मà¥\87ल à¤¸à¤\82दà¥\87श à¤¬à¤¦à¤²à¥\8dला",
+       "passwordreset-emailsentemail": "हà¥\8b à¤\88मà¥\87ल à¤ªà¤¤à¥\8dतà¥\8b à¤¤à¥\81à¤\9cà¥\8dया à¤¹à¤¿à¤¶à¥\8bबाà¤\82त à¤\9cà¥\8bडलà¥\8bलà¥\8bà¤\82 à¤\86सा à¤\9cालà¥\8dयार, à¤\97à¥\81पà¥\80तà¤\89तर à¤ªà¤°à¤¤à¥\82न à¤¥à¤¾à¤°à¤¾à¤µà¤ªà¤¾à¤\9aà¥\8b à¤\88मà¥\87ल à¤§à¤¾à¤¡à¤²à¥\87लà¥\87à¤\82 à¤\9cातà¥\87लà¥\87à¤\82.",
+       "changeemail": "à¤\88मà¥\87ल à¤ªà¤¤à¥\8dतà¥\8b à¤¬à¤¦à¤² à¤µà¤¾ à¤\95ाड",
        "changeemail-oldemail": "सद्याचो ईमेल नामो:",
        "changeemail-newemail": "नवो ईमेल नामो:",
        "changeemail-none": "(कांय ना)",
        "showpreview": "पूर्वनियाळ दाखय",
        "showdiff": "बदल दाखयात",
        "anoneditwarning": "'''शिटकावणी:''' तुवें सत्रारंभ करूंक ना.\nतुजो IP पत्तो ह्या पानाच्या संपादन इतिहासांत नोंद जातलो.जर तुमी <strong>[$1 सत्रारंभ]</strong> करता वा <strong>[$2 खातें उगडटा]</strong> जाल्यार हेर सुविधांसयत तुमच्या संपादनाचें श्रेय तुमच्या सदस्य नांवाचेर दितलें.",
-       "missingcommenttext": "à¤\89पà¤\95ार à¤\95रà¥\82न à¤¤à¥\81मà¤\9aà¥\8dयà¥\8b à¤¶à¤¿à¤°à¥\8b à¤¸à¤\95यल à¤\98ाल.",
+       "missingcommenttext": "à¤\89पà¤\95ार à¤\95रà¥\82न à¤¤à¥\81à¤\9cà¥\8b à¤¶à¥\87रà¥\8b à¤¬à¤°à¤¯.",
        "blockedtitle": "वापरप्याक बंद केला",
+       "blockedtext": "<strong>तुजें वापरप्याचें नांव वा आय पा पत्तो आडावपांत आयला.</strong>\n\nआडावप $1 हाणें केलां.\nकारण दिलां तें <em>$2</em>.\n\n* आडावपाची सुरवात: $8\n* आडावप सोंपोवपाचो वेळ: $6\n* आडावपाक येवजिला: $7\n\nतुज्यान $1-आक वा दूसऱ्या [[{{MediaWiki:Grouppage-sysop}}|कारभार्याक]] आडावणे विशीं भासाभास करुंक संपर्क करुंक जाता. तुज्यान \"{{int:emailuser}}\" सभावगूण वापरुंक जायना खेरीज एक वैद ईमेल पत्तो तुज्या [[Special:Preferences|खातें पसंतिंत]] निशचीत केल्या शिवाय आनी तुका तें वापरपाक आडावंक ना जाल्यार. तुजो चालंत IP पत्तो आसा $3, आनी आडावणेच्यो आंक #$5 आसा. सगळ्यो वयल्यो बारिकसाणी तूं करताय त्या विचारांत समावेश कर.",
        "blockednoreason": "कांयच कारण दिवंक ना",
        "loginreqtitle": "लॉग इन जाय",
        "loginreqlink": "सत्रारंभ करात",
        "accmailtitle": "गुपीत उतर धाडलां",
        "newarticle": "(नवें)",
        "newarticletext": "जें पान अजून अस्तित्वांत ना अशा पानाचे दुवे फाटल्यान तुमी आसात. पान रचपाक सकयले चौकटींत टायप करपाक सुरु करात (चड म्हायती खातीर [$1 आदाराचें पान] पळेयात) जर ह्या पानार तुमी चुकून पावल्यात तर ब्रावजराचो बॅक (<strong>फटीं</strong>) हो बटन दामात",
-       "noarticletext": "सद्या ह्या पानाचेर कसलीच मजकूर ना. \nतुमी हेर पानांचेर [[Special:Search/{{PAGENAME}}|हो माथाळो]] सोदूं शकतात,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} संबंदीत लॉग सोदूं शकतात],\nवा ह्या पानाक [{{fullurl:{{FULLPAGENAME}}|action=edit}} संपादीत] करूं शकतात</span>।",
+       "anontalkpagetext": "----\n<em>हें भासाभासेचें पान एक निनामी वापरप्याक जाणें अजून एक खातें उगडुंक ना, वो तो तें वापर्ना.</em>\nह्या खातीर आमकां आंकड्यांचो IP पत्तो वापरुंक पडता ताका वळखुंक.\nतसलो IP पत्तो साबार वापरप्यानी वापरूं येता.\nतूं जर एक निनामी वापरपी आसा आनी तुका दिसता की तुमका संबंद नासलेले शेरे तुजे विशीं केल्यात, उपकार करून [[Special:CreateAccount|एक खातें रच]] वा[[Special:UserLogin|सत्रारंभ कर]] फुडले गुस्पप निनामी वापरप्या ताळूंक.‎",
+       "noarticletext": "सध्याक हें पान रिंते आसा.\nतुज्यान दूसऱ्या पानानी [[Special:Search/{{PAGENAME}}| ह्या पानाचे नांव सोदूंक जाता]], <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAME}}}} संबंधी सत्रानी सोदूंक जाता], वा [{{fullurl:{{FULLPAGENAME}}|action=edit}} हें पान रचूंक जाता]</span>.",
        "noarticletext-nopermission": "तुर्ताक ह्या पानाचेर कसलोच मजकूर ना. तुमी हेर पानांचेर [[Special:Search/{{PAGENAME}}|ह्या माथाळ्याचो सोद]] घेवं शकतात,\nवा <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} संबंदीत लॉग सोदूं शकतात]</span>, पूण तुमकां हें पानाची रचणूक करपाची परवानगी ना।",
        "userpage-userdoesnotexist-view": "\"$1\" ह्या वापरप्याच्या खात्याची नोंदणी करूंक ना.",
+       "clearyourcache": "<strong>चत्राय:</strong> सांबाळ्ळ्या उपरांत, तुका घडयेक तुज्या ब्रावसराचो कॅश कडसरावंक पडत बदल पळोंवचे खातीर.\n* <strong>Firefox / Safari:</strong> <em>Shift</em> > धर <em>Reload</em> क्लीक करताना, वा दाम <em>Ctrl-F5</em> वा <em>Ctrl-R</em> (<em>⌘-R</em> मॅक-आचेर)\n* <strong>Google Chrome:</strong> <em>Ctrl-Shift-R</em> दाम (<em>⌘-Shift-R</em> एका मॅक-आचेर)\n* <strong>Internet Explorer:</strong> <em>Ctrl</em> dhor <em>Refresh</em> क्लीक करताना, वा दाम <em>Ctrl-F5</em>\n* <strong>Opera:</strong> हांगा वच: <em>Menu → Settings</em> (<em>Opera → Preferences</em> मॅक-आचेर) आनी उपरांत <em>Privacy & security → Clear browsing data → Cached images and files</em>.‎",
        "previewnote": "'''ही फकत एक दाखवण हें मतींत दवरात.'''\nतुमचें बदल आडून राखून दवरूंक ना!",
+       "continue-editing": "संपादन करपाच्या जाग्यार वच",
        "editing": "संपादता $1",
        "creating": "$1 रोचता",
        "editingsection": "(विभाग) $1 संपादन",
        "yourtext": "तुमचो मजकूर",
        "templatesused": "ह्या पानाचेर {{PLURAL:$1|वापरिल्लें}} सांचे",
+       "templatesusedpreview": "{{PLURAL:$1सांचो|सांचे}} ह्या झलकेंत वापरल्यात:‎",
        "template-protected": "(राखिल्लें)",
        "template-semiprotected": "(अर्द-सुरक्षीत)",
        "hiddencategories": "हें पान {{PLURAL:$1|लिपिल्ले वर्गाचें}} आसा",
+       "permissionserrors": "परवांगेची चूक",
        "permissionserrorstext-withaction": "ह्या {{PLURAL:$1|कारण|कारणां}}: खातीर तुका $2 मान्यताय ना.",
        "recreate-moveddeleted-warn": "शिटकावणीः तुमी आदीं काडून उडयिल्लें पान परतून तयार करतात ह्या पानाचे फासून उडोवपी आनी दुसरे कडे व्हरपी लाग फकत सोपेपणा खातीर दिल्यात",
-       "moveddeleted-notice": "हà¥\87à¤\82 à¤ªà¤¾à¤¨ à¤\95ाडà¥\82न à¤\89डयला.\nहà¥\8dया à¤ªà¤¾à¤¨à¤¾à¤\9aà¥\8b à¤\95ाडà¥\82न à¤\89डà¥\8bवपà¥\80 à¤\86नà¥\80 à¤¹à¤¾à¤²à¥\8bवपà¥\80 à¤²à¥\89à¤\97 संदर्भा खातीर सकयल दिला.",
+       "moveddeleted-notice": "हà¥\87à¤\82 à¤ªà¤¾à¤¨ à¤\95ाडà¥\82न à¤\89डयला.\nहà¥\8dया à¤ªà¤¾à¤¨à¤¾à¤\9aà¥\87à¤\82 à¤\95ाडà¥\82न à¤\89डà¥\8bवपाà¤\9aà¥\87à¤\82, à¤°à¤¾à¤\96पाà¤\9aà¥\87à¤\82, à¤\86नà¥\80 à¤¹à¤¾à¤²à¥\8bवपाà¤\9aà¥\87à¤\82 à¤¸à¤¤à¥\8dर  संदर्भा खातीर सकयल दिला.",
        "content-model-wikitext": "विकीमजकूर",
        "content-model-text": "सादोमजकूर",
        "post-expand-template-inclusion-warning": "<strong>शिटकावणीः</strong> सांचो धरून आकार अगडबंब जाता, कांय सांच्याचो आसपाव जावचो ना.",
        "post-expand-template-inclusion-category": "जंय सांचे धरून आवांठ व्हड जाता अशीं पानां",
        "post-expand-template-argument-warning": "<strong>शिटकावणीः</strong> ह्या पानाचेर खुब व्हड आंवाठ आशिल्लो एक तरी सांच्याचो मुद्दो आसा. हे मुद्दे भायरायल्यात",
        "post-expand-template-argument-category": "भायरायिल्ल्या सांच्यांसंबंदीचे मुद्दे आशिल्लीं पानां",
+       "undo-failure": "बदल परतावूंक जावंक ना कित्याक गुस्पणेचे मदले बदल आसात.",
        "viewpagelogs": "ह्या पाना खातीर सोत्रां पळेयात",
        "currentrev-asof": "$1 मेरेनचो सगळ्यांत निमणो पुनर्नियाळ",
        "revisionasof": " $1 मेरेन पुनर्नियाळ",
        "page_first": "पयलें",
        "page_last": "निमणें",
        "histlegend": "फरकाची निवडणी : पुनर्नियाळांची तुळा करपा खातीर रेडियो चौकटीं चेर कुरु करात आनी ''एंटर'' ना तर तळाकडे आशिल्लो बुतांव दामात।<br />\nविवरण : <strong>({{int:cur}})</strong> = हालींची पुनर्नियाळा बरोबर फरक, <strong>({{int:last}})</strong> = आदली पुनर्नियाळा बरोबर फरक, <strong>{{int:minoreditletter}}</strong> = दाक्टें बदल।",
-       "history-fieldset-title": "à¤\9aाळपाà¤\9aà¥\8b à¤\87तिहास",
-       "history-show-deleted": "फà¤\95त à¤\95ाडà¥\82न à¤\89डयिलà¥\8dलें",
+       "history-fieldset-title": "à¤\89à¤\9cळणà¥\8dयà¥\8b à¤\9aाळ",
+       "history-show-deleted": "फà¤\95त à¤\89à¤\9cळणà¥\80 à¤\95ाडà¥\82न à¤\89दयलà¥\87लें",
        "histfirst": "पोरणो",
        "histlast": "नवो ताल्ल",
+       "history-feed-title": "पुनर्नियाळाचो इतिहास",
+       "history-feed-description": "विकीचेर ह्या पाना खातीर पुनर्नियाळाचो इतिहास",
        "history-feed-item-nocomment": "$1 हांगा $2",
        "rev-delundel": "दृश्य मानताय बदलात",
        "rev-showdeleted": "दाखयात",
        "revdel-restore": "दृश्य मानताय बदलात",
        "pagehist": "पानाचो इतिहास",
        "mergehistory-reason": "कारण:",
+       "mergelog": "विलीन करपाचें सत्र",
        "revertmerge": "वेगळावप",
        "history-title": "\"$1\" च्या पुनर्नियाळाचो इतिहास",
        "difference-title": "\"$1\" च्या आवृत्तींत अंतर",
        "lineno": "$1 वळ :",
        "compareselectedversions": "वेंचिल्ल्या पुनर्नियाळांची तुळा करात",
        "editundo": "केल्लें परतावचें",
+       "diff-empty": "(कांय फरक ना)‎",
        "diff-multi-sameuser": "(ह्या वांगड्या सयत {{PLURAL:$1|केल्लें मदलें एक अवतरण दाखोवंक ना|केल्लें मदलें $1 अवतरण दाखोवंक ना}})",
+       "diff-multi-otherusers": "({{PLURAL:$2|एक हेर वापरप्या|$2 हेर वापरप्यां}} वर्वीं {{PLURAL:$1|एक मदली उजळणी|$1 मदल्यो उजळण्यो}} दाखोवंक ना)‎",
        "searchresults": "सोदाचो निकाल",
        "searchresults-title": "\"$1\" हाच्या सोदाचे परिणामां",
        "prevn": "आदलें{{PLURAL:$1|$1}}",
        "searchprofile-everything-tooltip": "सगळो मजकूर सोदात(चर्चेचें पाना सयत)",
        "searchprofile-advanced-tooltip": "खाशेल्या नांवथोळाणी सोदात",
        "search-result-size": "$1 ({{PLURAL:$2|1 उतर|$2 उतरां}})",
-       "search-result-category-size": "{PLURAL:$1|1 सदस्य|$1 सदस्य}} ({{PLURAL:$2|1 उपगट|$2 उपगट}}, {{PLURAL:$3|1 फायल|$3 फायलीं}})",
-       "search-redirect": "(पुनर्निर्देशन $1)",
+       "search-result-category-size": "{{PLURAL:$1|$1 वांगडी}} ({{PLURAL:$2|$2 उपवर्ग}}, {{PLURAL:$3|1 फायल|$3 फायली}})",
+       "search-redirect": "($1 सावन पुनर्निर्देशीत)",
        "search-section": "(विभाग $1)",
+       "search-file-match": "(फायलीच्या मजकुराक जुळटा)‎",
        "search-suggest": "तुमकां $1 अशें म्हणपाचें आसलें?",
        "search-rewritten": "$1 हाचो निकाल दाखयता.नाजाल्यार $2 हें सोदात.",
        "search-interwiki-more": "(आनी)",
        "prefs-watchlist": "सादुरवळेरी",
        "youremail": "इमेल",
        "yourrealname": "खरें नांवः",
+       "group-bot": "रोबोटां",
+       "group-sysop": "कारभारी",
+       "grouppage-bot": "{{ns:project}}:रोबोटां",
+       "grouppage-sysop": "{{ns:project}}:कारभारी",
        "right-writeapi": "Write API चो उपेग",
        "newuserlogpage": "वापरपी रोचनेचे वळेरी",
+       "rightslog": "वापरप्याच्या हकांचो सत्र",
        "action-edit": "हें पान संपादीत कर",
-       "nchanges": "$1 {{PLURAL:$1|बदल|बदल}}",
+       "action-createaccount": "हें वापरप्याचें खातें रच",
+       "nchanges": "$1 {{PLURAL:$1|बदल}}",
        "enhancedrc-history": "इतिहास",
        "recentchanges": "हालींचे बदल",
        "recentchanges-legend": "हालींच जाल्ल्या बदलाचो विकल्प",
        "recentchanges-summary": "ह्या विकीचेर हालींच जाल्ल्या बदलांचो माग ह्या भरणांतल्यान दवरात",
+       "recentchanges-noresult": "दिलेल्या काळाचे बदल ह्या निकशाक जुळनांत.‎",
        "recentchanges-feed-description": "ह्या विकीचेर हालींच जाल्ल्या बदलांचो माग ह्या भरणांतल्यान दवरात.",
        "recentchanges-label-newpage": "ह्या संपादनांन नवें पान निर्माण केला.",
        "recentchanges-label-minor": "हें दाक्टे संपादन",
        "recentchanges-label-plusminus": "ह्या पानाचो आकार इतल्या बाइट्सन बदललो",
        "recentchanges-legend-heading": "<strong>कुंजी:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages| नव्या पानांची सुची]] पळयात)",
-       "rcnotefrom": "$2 पासून केल्ले बदल सकयल दिल्यात ($1 मेरेन दाखयल्यात)",
+       "rcnotefrom": "सकयल <strong>$3, $4</strong> सावन {{PLURAL:$5 जालेले बदल दिल्यात}} (<strong>$1</strong> मेरेन {{PLURAL:$5|दाखयलां|दाखयल्यांत}}).",
        "rclistfrom": "$3 $2 साकून नवें बदल दाखयात",
        "rcshowhideminor": "$1 दाकट्यो बदल",
        "rcshowhideminor-show": "दाखयात",
        "rcshowhidebots-show": "दाखयात",
        "rcshowhidebots-hide": "लिपयात",
        "rcshowhideliu": "$1 अधिकृत नोंदीचे वापरपी",
+       "rcshowhideliu-show": "दाखयात",
        "rcshowhideliu-hide": "लिपयात",
        "rcshowhideanons": "$1 निनांवी वापरपी",
        "rcshowhideanons-show": "दाखयात",
        "rcshowhideanons-hide": "लिपयात",
+       "rcshowhidepatr": "$1 पारो केलेले सुदारप",
        "rcshowhidepatr-show": "दाखयात",
        "rcshowhidepatr-hide": "लिपयात",
        "rcshowhidemine": "$1 म्हजें संपादन आंकडे",
        "rcshowhidemine-show": "दाखयात",
        "rcshowhidemine-hide": "लिपयात",
-       "rclinks": "फाà¤\9fलà¥\8dया $2 à¤¦à¤¿à¤¸à¤¾à¤\82नà¥\80 à¤\9cालà¥\8dलà¥\8b $1 बदल दाखयात",
+       "rclinks": "शà¥\87वà¤\9fà¤\9aà¥\87 $2 à¤¦à¤¿à¤¸à¤¾à¤¨à¥\80à¤\82 à¤\9cालà¥\8dलà¥\87 $1 बदल दाखयात",
        "diff": "फरक",
        "hist": "इति",
        "hide": "लिपयात",
        "minoreditletter": "द",
        "newpageletter": "न",
        "boteditletter": "र",
-       "rc-change-size-new": "$1 {{बहुवचन:$1|byte|bytes}}बदल केल्या उपरांत",
+       "rc-change-size-new": "$1 {{PLURAL:$1|बाय्ट|बाय्टी}} बदल केल्या उपरांत",
        "rc-enhanced-expand": "म्हायती दाखय",
        "rc-enhanced-hide": "म्हायती लिपय",
+       "rc-old-title": "आरंभांत रचलली \"$1\" ह्या नांवान‎",
        "recentchangeslinked": "संबंदित बदल",
        "recentchangeslinked-toolbox": "संबंदीत बदल",
        "recentchangeslinked-title": "\"$1\" च्या संबंदातले बदल",
-       "recentchangeslinked-summary": "à¤\96ाशà¥\87लà¥\8dया à¤ªà¤¾à¤¨à¤¾à¤\82 à¤\95डलà¥\8dयान à¤¦à¥\81वà¥\87 à¤®à¥\87ळिलà¥\8dलà¥\8dया à¤ªà¤¾à¤¨à¤¾à¤\82मदà¥\80à¤\82 (वा à¤µà¤¿à¤¶à¤¿à¤¶à¥\8dà¤\9f à¤µà¤°à¥\8dà¤\97ाà¤\82à¤\9aà¥\8dया à¤µà¤¾à¤\82à¤\97डà¥\8dयाà¤\82मदà¥\80à¤\82) à¤¹à¤¾à¤²à¥\80à¤\82à¤\9a à¤\95à¥\87लà¥\8dलà¥\8dया à¤¬à¤¦à¤²à¤¾à¤\82à¤\9aà¥\80 à¤¹à¥\80 à¤µà¤³à¥\87रà¥\80. [[Special:Watchlist|तà¥\81मà¤\9aà¥\8dया à¤¸à¤¾à¤¦à¥\81रवळà¥\87रà¥\80]] à¤ªà¤¾à¤¨à¤¾ '''ठळà¤\95''' à¤¦à¤¾à¤\96यलà¥\8dयात",
+       "recentchangeslinked-summary": "à¤\8fà¤\95ा à¤ªà¤¾à¤¨à¤¾à¤\9aà¥\87à¤\82 à¤¨à¤¾à¤\82व à¤¬à¤°à¤¯ à¤\9cà¥\8dया à¤µà¤°à¥\8dवà¥\80à¤\82 à¤\9cडलà¥\87लà¥\8dया à¤ªà¤¾à¤¨à¤¾à¤\82à¤\9aà¥\87र à¤µà¤¾ à¤ªà¤¾à¤¨à¤¾à¤\82 à¤ªà¤¾à¤¸à¥\82न à¤¬à¤¦à¤² à¤¦à¤¿à¤¸à¤¤à¤²à¥\8b. (à¤\8fà¤\95ा à¤µà¤°à¥\8dà¤\97णाà¤\9aà¥\87 à¤µà¤¾à¤\82à¤\97डà¥\80 à¤ªà¤³à¥\8bवà¤\82à¤\95, à¤¬à¤°à¤¯ {{ns:category}}:वरà¥\8dà¤\97ाà¤\9aà¥\87à¤\82 à¤¨à¤¾à¤\82व). [[Special:Watchlist|तà¥\81à¤\9cà¥\8dया à¤¸à¤¾à¤¦à¥\81रवळà¥\87रà¥\80à¤\82त]] à¤\86सलà¥\87लà¥\8dया à¤ªà¤¾à¤¨à¤¾à¤\9aà¥\87र à¤¬à¤¦à¤² <strong>दाà¤\9f</strong> à¤\86सात.",
        "recentchangeslinked-page": "पानाचें नांव",
        "recentchangeslinked-to": "ह्या पाना बदला दिल्ल्या पानांक जडून आशिल्ल्या पानांचे बदल दाखय",
        "upload": "फायल अपलोड करात",
        "uploadbtn": "फायल अपलोड करात",
+       "uploadlogpage": "अपलोडाचें सत्र",
        "filedesc": "सारांश",
        "fileuploadsummary": "आपरोस:",
        "license": "लायसन्सीग",
        "filehist-datetime": "दिस / वेळ",
        "filehist-thumb": "ल्हान-इमाज़",
        "filehist-thumbtext": " $1मेरेनचे आवृत्ती खातीर ल्हान-इमाज़",
+       "filehist-nothumb": "ल्हान-इमाज ना",
        "filehist-user": "वापरपी",
        "filehist-dimensions": "परिमाण",
        "filehist-comment": "शेरो",
        "imagelinks": "फायलिचो वापर",
-       "linkstoimage": "हे फायलीक सकयल दिल्ल्यो पानाच्यो जोडण्यो {{PLURAL:$1|आसात}}.",
-       "nolinkstoimage": "हे फायलीक दुवो आशिल्लीं आनीक पानां नात.",
+       "linkstoimage": "{{PLURAL:$1|हें पान|$1 हीं पानां}} ही फायल {{PLURAL:$1|वापरता|वापरतात}}:",
+       "linkstoimage-more": "$1 परस अदीक {{PLURAL:$1|पान वापरता|पानां वापरतात}} ही फायल.\nसकयली वळेरी दाखयता {{PLURAL:$1|पयलें पान|पयलीं $1 पानां}} जें हीच फायल वापरता. एक [[Special:WhatLinksHere/$2|पूर्ण वळेरी]] उपलब्ध आसा.‎",
+       "nolinkstoimage": "ह्या फायलीक वापरतात तसलीं पानां नांत.",
+       "linkstoimage-redirect": "$1 (फायल पुनर्देशन) $2",
        "sharedupload-desc-here": "ही फयल $1 हांगाची आनी ती हे प्रकल्पां खातीर वापरल्यार चलता. (तिच्या $2 ह्या फयलींतलें वर्णनाचे पान) तातूंतलें वर्णन सकयल दिलां.",
+       "filepage-nofile": "ह्या नांवाची फायल असतित्वांत ना.",
        "upload-disallowed-here": "तूं ह्या फायलीचेर अधिलेखीत करूंक शकना",
        "randompage": "खंयचेंय पान",
        "statistics": "संख्याशास्त्र",
        "statistics-pages": "पान:",
        "statistics-files": "फायल अपलोड करात",
+       "double-redirect-fixer": "पुनर्निर्देशन थारावपी",
        "brokenredirects-edit": "बदल",
        "brokenredirects-delete": "काडून उडयात",
        "nbytes": "$1 {{PLURAL:$1|बाय्ट}}",
        "nmembers": "$1 {{PLURAL:$1|वांगडी}}",
        "prefixindex": "उपसर्ग आशिल्लीं सगळीं पानां",
-       "usercreated": "$1 ह्या दिसा $2 ह्या वेळार तयार केलें",
+       "listusers": "वापरप्यांची वळेरी",
+       "usercreated": "$3 हाणें $1 दिसा $2 वोराचेर {{GENDER:$3|रचलेलें}}",
        "newpages": "नवीं पानां",
        "move": "हालय",
        "pager-newer-n": "{{PLURAL:$1|नवो 1|नवें $1}}",
        "booksources": "पुस्तकांचो स्त्रोत",
        "booksources-search-legend": "पुस्तकाचे स्त्रोत सोदात",
        "booksources-search": "सोद",
+       "specialloguserlabel": "करपी:",
+       "speciallogtitlelabel": "मोख (माथाळो वा {{ns:user}}:वापरप्याचें नांव):",
        "log": "सोत्रां",
+       "all-logs-page": "सगळीं भौसाचीं सत्रां",
+       "alllogstext": "{{SITENAME}} हाच्यो सगळ्या उपलब्ध सत्रांची एकठांय दाखोवणी.\nतुज्यान तुजो देखावो अर्नूं येता एक सत्राचो प्रकार विंचून, वापरप्याचें नांव (व्हदल्या आनी धाकट्या अक्षरा मदें फरक पडटा), वा पोरणें जालेलें पान (हांगाय व्ह़डले आनी धाक्टे अक्षरा मदें फरक पडटा).‎",
+       "logempty": "सत्रान जुळपी नग नांत.‎",
        "allpages": "सगळीं पाना",
        "nextpage": "फुडलें पान ($1)",
        "prevpage": "फाटलें पान ($1)",
        "allarticles": "सगळीं पानां",
        "allpagessubmit": "वचात",
+       "allpages-hide-redirects": "पुनर्देर्शनां लिपय",
        "categories": "वर्ग",
        "linksearch-ns": "नांवाची सुवात",
        "linksearch-ok": "सोद",
        "listgrouprights-members": "सदस्यांची वळेरी",
        "emailuser": "ह्या वापरप्याक इमेल करात.",
        "emailusername": "वापरप्याचे नांव",
+       "usermessage-editor": "यंत्रणाचो संदेशकार",
        "watchlist": "सादुरवळेरी",
        "mywatchlist": "सादुरवळेरी",
        "watchlistfor2": "$1 $2 खातीर",
        "addedwatchtext": "\"[[:$1]]\" आनी हाचे भासाभास पान तुमचें [[Special:Watchlist|सादुरवळेरेक]] जोडलां.",
        "watch": "नदर दवरात",
        "unwatch": "पळोवंक नासलें",
-       "watchlist-details": "लक्ष {{PLURAL:$1|$1वळेरींतलें|$1 वळेंरींतली}} {{PLURAL:$1|$1पान|$1 पानां}} उलोवपाची पानां सोडून",
+       "watchlist-details": "तुज्या सादूरवळेरिंत {{PLURAL:$1|$1 पान आसा|$1 पानां आसात}} (त्या भायर उलोवपाचीं पानां आसात).",
+       "wlheader-showupdated": "तुज्या फाटले भेटे सावन बदल्ल्यान तीं पानां <strong>दाट</strong> दाखयल्यांत.",
+       "wlnote": "सकयल {{PLURAL:$1|हो निमाणो बदल|हें निमाण्यो <strong>$1</strong> बदल}} निमाण्या {{PLURAL:$2|वोरान|<strong>$2</strong>वोरानीं}}, $3, $4 पर्यान.‎",
        "watchlist-options": "सादुरवळेरींतलो पर्याय",
+       "enotif_reset": "सगळीं पानां भेट दिलेलीं म्हूण खुणाय",
        "delete-legend": "काडून उडयात",
        "actioncomplete": "क्रिया पुराय जाल्या",
        "actionfailed": "क्रिया अपेस जाल्या",
        "changecontentmodel-reason-label": "कारण:",
        "protectlogpage": "सुरक्षितेचें सोत्र",
        "protectedarticle": "राखिल्ले\"[[$1]]\"",
+       "modifiedarticleprotection": "सुरक्षेची पातळी \"[[$1]]\"‎ हाचे खातीर बदल्ल्या",
+       "protect-default": "सगळ्या वापरप्यांक परवांगी दी",
        "restriction-edit": "बदल",
        "restriction-move": "दुसरेकडे व्हरात",
        "restriction-create": "निर्माण कर",
        "contributions-title": "$1 खातीर वापरप्याचीं योगदानां",
        "mycontris": "योगदान",
        "anoncontribs": "योगदान",
+       "contribsub2": "{{GENDER:$3|$1}} हाच्यो ($2)",
+       "nocontribs": "ह्या निशकशांक खयंचेच बदल जूळ्ळेले मेळूंक नांत.",
        "uctop": "हालीचें",
        "month": "ह्या म्हयन्या सावन (आनी आदलें):",
        "year": "ह्या वर्सा सावन (आनी आदलें):",
        "sp-contributions-search": "योगदानां सोदात",
        "sp-contributions-username": "आयपी नामो वा वापरप्याचें नांव",
        "sp-contributions-toponly": "फकत सगळ्यांत हालींचे पुनर्नियाळ आशिल्लीं संपादन दाखयात",
+       "sp-contributions-newonly": "फकत तसलेचच बदल दाखय, जांचे वर्वीं पान रचलां",
        "sp-contributions-submit": "सोद",
        "whatlinkshere": "हाका कितें जडता",
        "whatlinkshere-title": " \"$1\" हाका दुवे आशिल्लीं पानां",
        "linkshere": "मुखावेली पानां <strong>$2</strong>: हाका जडतात",
        "nolinkshere": "<strong>$2</strong> हाका खंयच्याच पानाचो दुवो ना",
        "isredirect": "पुनर्निर्देशन पान",
-       "istemplate": "$1 दूसरात-समावेस",
+       "istemplate": "दुरास्थ-समावेस",
        "isimage": "फायलीचो दुवो",
        "whatlinkshere-prev": "{{PLURAL:$1|आदलें|आदलीं $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|फुडलें|फुडलें $1}}",
        "whatlinkshere-links": "← दुवे",
        "whatlinkshere-hideredirs": "$1 पुनर्निर्देशन",
-       "whatlinkshere-hidetrans": "$1 à¤¦à¥\82सà¥\8dरात-समावà¥\87श",
+       "whatlinkshere-hidetrans": "$1 à¤¦à¥\81रासà¥\8dथ-समावà¥\87स",
        "whatlinkshere-hidelinks": "$1 दुवे",
-       "whatlinkshere-hideimages": "$1 फायल दुवे",
+       "whatlinkshere-hideimages": "$1 फायलींचे दुवे",
        "whatlinkshere-filters": "गाळणे",
-       "ipboptions": "2 वरां: 2hours ,1 दीस:1 day,3 दीस:3 days,1 सुमान:1 week,2 सुमनां:2 weeks,1 म्हयनो:1 month,3 म्हयने:3 months,6 म्हयने:6 months,1 वर्स:1 year,अनिश्चीत:infinte",
+       "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",
        "ipblocklist": "आडायल्लें वापरपी",
+       "infiniteblock": "शेवट ना",
        "blocklink": "आडावणी",
        "change-blocklink": "विभाग सुदारप",
        "contribslink": "योगदान",
        "blocklogpage": "कार्यवळेरी आडायात",
-       "blocklogentry": "$2 $3 हो सोंपपी वेळ आशिल्लो $1 बंद दवरल्ला",
+       "blocklogentry": "[[$1]] आक आडायला, इतल्या वेळाक: $2, कारण: $3",
+       "reblock-logentry": "आडावपाचें बसोवप बदल्लां [[$1]] हाचे खातीर सोंपोवपाचो वेळ दिला $2 $3‎",
        "block-log-flags-nocreate": "खातें निर्माण जावूंक ना",
+       "proxyblocker": "प्रतिनिधी सिरविदोर आडावपी‎",
        "movepagebtn": "पान हालय",
        "movelogpage": "पान हालोवण्यांचो सोत्र",
        "revertmove": "मूळ पदार व्हरप",
        "allmessagesdefault": "पूर्वनिर्धारित संदेशाचो मजकूर",
        "thumbnail-more": "व्हड करात",
        "thumbnail_error": "$1ः लघुप्रतिमा करतांनाची चूक",
-       "tooltip-pt-userpage": "तुमचें वापरपाचें पान",
-       "tooltip-pt-mytalk": "तुमचें चर्चेचें पान",
+       "importlogpage": "आयाताचें सत्र",
+       "tooltip-pt-userpage": "{{GENDER:|तुमचें वापरप्याचें}} पान",
+       "tooltip-pt-mytalk": "{{GENDER:|तुमचें}} भासाभासाचें पान",
        "tooltip-pt-preferences": "{{GENDER:|तुमची}} पसंती",
        "tooltip-pt-watchlist": "तुमी बदल करपा खातीर देखरेख करतात त्या पानांची वळेरी",
-       "tooltip-pt-mycontris": "तुमच्या योगदानांची वळेरी",
+       "tooltip-pt-mycontris": "{{GENDER:|तुमच्या}} योगदानांची वळेरी",
        "tooltip-pt-login": "सत्रारंभ करप बरें, पूण तशी सक्ती ना.",
        "tooltip-pt-logout": "सत्र शेवट",
        "tooltip-pt-createaccount": "तुमी खातें उगडून सत्रारंभ करचें अशें सुचयतात, पूण तें सक्तीचें ना.",
        "tooltip-t-whatlinkshere": "हांगा दुवे आशिल्ल्या सगळ्या विकी पानांची वळेरी",
        "tooltip-t-recentchangeslinked": "ह्या पानावेल्यान दुवे दिल्ल्या पानांतले हालींचे बदल",
        "tooltip-feed-atom": "ह्या पाना खातीर ऍटम पूर्वण",
-       "tooltip-t-contributions": "ह्या वापरप्याची योगदानाची वळेरी",
+       "tooltip-t-contributions": "{{GENDER:$1|ह्या वापरप्याची}} योगदानाची वळेरी",
        "tooltip-t-emailuser": "{{GENDER:$1|ह्या उपेगकर्त्याक}} इ-मेल धाडात",
        "tooltip-t-upload": "फायली अपलोड करात",
        "tooltip-t-specialpages": "सगळ्या विशेश पानांची वळेरी",
        "tooltip-t-permalink": "ह्या पानाच्या ह्या पुनर्नियाळाकडे सदांकाळ दुवो",
        "tooltip-ca-nstab-main": "मजकूर पान पळेयात",
        "tooltip-ca-nstab-user": "वापरप्याचें पान दाखय",
-       "tooltip-ca-nstab-special": "हà¥\87à¤\82 à¤\96à¥\87रà¥\80त à¤ªà¤¾à¤¨, à¤¤à¥\81मà¤\9aà¥\8dयाà¤\82नà¥\80à¤\82 à¤\96à¥\81दà¥\8dद à¤¤à¥\8dया à¤ªà¤¾à¤¨à¤¾à¤° à¤¸à¤\82सà¥\8dà¤\95रण à¤\95रà¥\82à¤\82 à¤¨à¤\9cà¥\8b",
+       "tooltip-ca-nstab-special": "हà¥\87à¤\82 à¤\8fà¤\95 à¤\96à¥\87रà¥\80त à¤ªà¤¾à¤¨, à¤\86नà¥\80 à¤¹à¥\87à¤\82 à¤¬à¤¦à¤²à¥\82à¤\82à¤\95 à¤\9cायना",
        "tooltip-ca-nstab-project": "प्रकल्पाचें पान पळेयात",
        "tooltip-ca-nstab-image": "फायलीचें पान पळेयात",
+       "tooltip-ca-nstab-mediawiki": "यंत्रणाचो संदेश पळय",
        "tooltip-ca-nstab-template": "सांचो पळेयात",
        "tooltip-ca-nstab-category": "वर्गांचे पान पळेयात",
        "tooltip-minoredit": "हो ल्हानसो बदल म्हूण कुरू करात",
        "tooltip-rollback": "निमाण्या योगदान करप्यान ह्या पानाचेर केल्लें संपादन रोलबॅक  (फाटीं घेयात) एकाच क्लीकान मूळ पदार हाडटा",
        "tooltip-undo": "\"आदलें स्थितीर हाडचें\" ह्या बदलाक परत व्हरुन संपादन स्थितीन झलक रितीन दाखयतात.\nहाचेवरवीं सारांशान आदल्या स्थितीर हाडपाचें कारण बरोवं शकता.",
        "tooltip-summary": "आपरोसाची नोंदणी करात",
-       "simpleantispam-label": "एन्टी-स्पैम तपासप.\nहे भरी<strong>नकाय</strong>!",
+       "simpleantispam-label": "स्पमविरूध तपासणी.\nहें भर <strong>नाका</strong>!",
+       "pageinfo-title": "\"$1\" ‎खातीर म्हायती",
+       "pageinfo-header-basic": "मूळ म्हायती",
+       "pageinfo-header-edits": "बदलाचो इतिहास",
+       "pageinfo-header-restrictions": "पानाची सुरक्षा",
+       "pageinfo-header-properties": "पानाचे गुणधर्म",
+       "pageinfo-display-title": "मांडलेलें माथाळें",
+       "pageinfo-default-sort": "डिफोल्ट आरीन मांडूंक चावी",
+       "pageinfo-length": "पानाची लांबाय (बायटांत)‎",
+       "pageinfo-article-id": "पानाचो आंक",
+       "pageinfo-language": "पानाच्या मजकुराची भास",
+       "pageinfo-content-model": "पानाच्या मजकुराचो नमुनो",
+       "pageinfo-robot-policy": "रोबोटां कडल्यान सुचेंत घालप",
+       "pageinfo-robot-index": "परवांगी आसा",
+       "pageinfo-robot-noindex": "परवांगी ना",
+       "pageinfo-watchers": "पानाचेर दिश्ट दवरतेल्यांचो आंकडो",
+       "pageinfo-few-watchers": "$1 परस थोडें {{PLURAL:$1|दिश्ट दवरपी}}‎",
+       "pageinfo-redirects-name": "ह्या पाना खातीर पुनर्निर्देशनांचो आंकडो",
+       "pageinfo-subpages-name": "ह्या पानाच्या ऊप-पानाचो आंकडो",
+       "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|पुनर्निर्देशन|पुनर्निर्देशनां}}; $3 {{PLURAL:$3|पुनर्निर्देशन नासलेलें}})‎",
+       "pageinfo-firstuser": "पान रचपी",
+       "pageinfo-firsttime": "पान रचपाची तारीख",
+       "pageinfo-lastuser": "हालींचो संपादक",
+       "pageinfo-lasttime": "हालींच्या बदलाची तारीख",
+       "pageinfo-edits": "एकूण बदलाचो आंकडो",
+       "pageinfo-authors": "वेगळे बरोवप्यांचो एकूण आंकडो",
+       "pageinfo-recent-edits": "हालींच्या बदलांचे आंकडे (गेले $1)‎",
+       "pageinfo-recent-authors": "हालींचे वेगळे बरोवपी",
+       "pageinfo-magic-words": "{{PLURAL:$1|जादवाचें उतर|जादवाचीं उतरां}} ($1)‎",
+       "pageinfo-hidden-categories": "लिपयलेले {{PLURAL:$1|वर्ग}} ($1)",
+       "pageinfo-templates": "{{PLURAL:$1|सांचो दुरास्थ-समावेस जाला|सांचे दुरास्थ-समावेस जाले}} ($1)‎",
        "pageinfo-toolboxlink": "पानाची म्हायती",
+       "pageinfo-contentpage": "एक मजकुराचें पान कशें धरपांत आयलां",
        "pageinfo-contentpage-yes": "हय",
+       "patrol-log-page": "पारो करप्याचे सत्र",
        "previousdiff": "← आदलें संपादन",
        "nextdiff": "नवें संपादन →",
+       "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|पान|पानां}}",
        "file-info-size": "$1 × $2 चित्रतत्व, फायलीचो आकार: $3, माइम प्रकार: $4",
+       "file-info-size-pages": "$1 × $2 चित्रत्वां, फायलिचो आकार: $3, MIME प्रकार: $4, $5 {{PLURAL:$5|पान|पानां}}‎",
        "file-nohires": "हाच्या परस वयले बारिक्साय उपल्बद ना",
        "svg-long-desc": "SVG फायल, नांवाक $1 × $2 चित्रतत्वां, फायलीचो आकार: $3",
        "show-big-image": "मुळावी फायल",
        "monthsall": "सगळे",
        "confirm-rollback-button": "बरें",
        "confirm-rollback-top": "ह्या पाना वयलें संपादन आशिल्ले तशें करात?",
+       "imgmultipagenext": "फुडलें पान →",
+       "imgmultigo": "वचात!",
+       "imgmultigoto": "$1 ‎पानार वचात",
+       "watchlisttools-clear": "सादूरवळेरी निवळ कर",
        "watchlisttools-view": "प्रस्तूत बदल पळयात.",
        "watchlisttools-edit": "सादुरवळेरी पळय आनी संपादीत करात",
+       "watchlisttools-raw": "सादूरवळेरिची मूळान बदल कर",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|उलयात]])",
+       "redirect": "फायल, वापरपी, पान, उजळणी वा सत्र आंक‎ वर्वीं पुनर्देशन कर",
+       "redirect-summary": "हें विशेश पान पुनर्देशीत करता एका फायलीक (फायलीचें नांव दिल्यार), एका पानाक (उजळणेचो आंक वा पानाचो आंक दिल्यार), एक वापरप्याच्या पानाक (एके वापरप्याचो आंक दिल्यार), वा एक सत्र नोंद (सत्राचो आंक दिल्यार). वापर: [[{{#Special:Redirect}}/file/देखीक.jpg]],  [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], vo [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "वचात",
+       "redirect-lookup": "सुचींत पळय:",
        "redirect-value": "मोल:",
+       "redirect-user": "वापरप्यांचो आंक",
+       "redirect-page": "पानाचो आंक",
+       "redirect-revision": "पानाची उजळणी",
+       "redirect-file": "फायलीचें नांव",
        "specialpages": "विशेश पानां",
        "tag-filter": "[[Special:Tags|कुर्वेचीट]] गाळणो:",
        "tag-list-wrapper": "[[Special:Tags|{{PLURAL:$1|कुरवेचीट|कुरवेचीटी}}]]: $2",
        "tags-active-yes": "हय",
        "tags-active-no": "ना",
+       "tags-hitcount": "$1 {{PLURAL:$1|बदल}}",
        "htmlform-title-not-exists": "$1 अस्तित्वांत ना.",
        "logentry-delete-delete": "$1 {{GENDER:$2|काडून उडयल्ले पान}} $3",
+       "logentry-delete-restore": "$1 हाणें {{GENDER:$2|परत हाडलां}} पान $3 ($4)‎",
+       "logentry-delete-revision": "$1 हाणें {{PLURAL:$5|उजळणेचें}} दिसणे  $3, ह्या पानार {{GENDER:$2|बदल्ला}}: $4‎",
+       "revdelete-content-hid": "मजकूर लिपयला",
        "logentry-move-move": "$1 हाणें $3 पानाक $4 {{GENDER:$2|हालयला}}",
+       "logentry-move-move-noredirect": "$1, हाणें पान $3 सावन $4 {{GENDER:$2|हालयलां}} पुनर्देर्शन दवरिनासतानां",
+       "logentry-move-move_redir": "$1 हाणें पान $3 सावन $4 {{GENDER:$2||हालयल्लो}} पुनर्दिशनावयर",
+       "logentry-patrol-patrol-auto": "$1-आन $3, ह्या पानाचें $4, ह्या उजळणेचो पारो केलां म्हण आपोआप {{GENDER:$2|खुणायलां}}",
        "logentry-newusers-create": "उपयोगकत्याचें $1 {{GENDER:$2|तयार केलें}}",
+       "logentry-newusers-autocreate": "वापरप्याचें खातें $1 आपोआप {{GENDER:$2|रचून}} आयलें",
        "logentry-upload-upload": "$1 {{GENDER:$2|अपलोड केला}} $3",
+       "logentry-upload-overwrite": "$1, हाणें $3‎, हाची एक नवी आवृत्ती {{GENDER:$2|अपलोड केलां}}",
        "searchsuggest-search": "{{SITENAME}} सोद",
+       "duration-days": "$1 {{PLURAL:$1|दीस}}",
        "special-characters-group-latin": "रोमी",
        "special-characters-group-latinextended": "रोमी (आनिंक-उइ)",
        "special-characters-group-ipa": "IPA",
        "special-characters-group-khmer": "ख्मेर",
        "mw-widgets-dateinput-no-date": "तारीख निवडूंक ना",
        "mw-widgets-dateinput-placeholder-day": "वर्स-म्हयनो-दीस",
-       "mw-widgets-dateinput-placeholder-month": "वर्स-म्हयनो"
+       "mw-widgets-dateinput-placeholder-month": "वर्स-म्हयनो",
+       "randomrootpage": "खयंचेंय मूळ पान"
 }
index 51842f5..6832f35 100644 (file)
@@ -17,7 +17,7 @@
        "tog-enotifwatchlistpages": "Mhojea sadurvollerintlem pan vo fayl bodol'li zalear mhaka email dhadd",
        "tog-shownumberswatching": "Nodor dovorpi vaporpeanche sonkhya dakhoi",
        "tog-oldsig": "Tujea sod'dheachi soy:",
-       "tog-uselivepreview": "Pan porot ugdinastana zolok dahkoi",
+       "tog-uselivepreview": "Pan porot ughoddnastana zholok dakhoi",
        "tog-watchlisthideown": "Sadurvollerint mhoje bodol lipoi",
        "tog-watchlisthidebots": "Sadurvollerint robotani kel'le bodol lipoi",
        "tog-watchlisthideminor": "Sadurvollerint dhaktem bodol lipoi",
        "listingcontinuesabbrev": "chalu",
        "index-category": "Suchi-potran zodlelim panam",
        "noindex-category": "Suchi-potran zoddunk-naslelim panam",
-       "broken-file-category": "Tuttlolea faylinchea duve aslelim panam‎",
+       "broken-file-category": "Tuttlolea faylinche duve aslelim panam‎",
        "about": "Hea vixoiavoir",
        "article": "Vixoi sombondhi pan",
        "newwindow": "(novea zonelant uktem zata)",
        "redirectedfrom": "($1 savn punornirdexit)",
        "redirectpagesub": "Punornirdexan pan",
        "redirectto": "Hanga ponornirdeshit:",
-       "lastmodifiedat": "Hem pan xevtim $1 disa, $2 vazta bodolelem.",
+       "lastmodifiedat": "Hem pan xevttim $1 disa, $2 vorancher bodololem.",
        "protectedpage": "Rakhun dovorl'lem pan",
        "jumpto": "Hupun voch",
        "jumptonavigation": "dixa-niontronn",
        "youhavenewmessages": "Tumkam $1 ($2) asat.",
        "youhavenewmessagesfromusers": "Tuka {{PLURAL:$3|ek vaporpi|$3 vaporpi}} koddlean $1 {{PLURAL:$4|asa|asat}} ($2).‎",
        "newmessageslinkplural": "{{PLURAL:$1|novo sondex|999=nove sondex}}‎",
-       "newmessagesdifflinkplural": "{{PLURAL:$1|nimanno bodol|999=nimanneo bodol}}",
+       "newmessagesdifflinkplural": "{{PLURAL:$1|nimanno bodol|999=nimanne bodol}}",
        "youhavenewmessagesmulti": "$1 cher tuka noveo sondex asat",
        "editsection": "bodol",
        "editold": "bodol",
        "databaseerror-textcl": "Totv-kox (database) sodtana chuk ghodli",
        "databaseerror-query": "Anurodh: $1",
        "databaseerror-error": "Chuk: $1",
-       "missing-article": "Totv-kox (Database) hantun mellunk zai aslem tem mozkur \"$1\" $2 mellunk-nam.\n\nHorxim, oxem ek pornem frk vo eka panachea itihasacho duvo kadun udoila, tedna zata.\n\nOxem nhoi zalear, tuka softwer-an chuk sampodlam zait.\nUpkar korun eka [[Special:ListUsers/sysop|karbhari]]chea nodrek hadd, Internet Zago Sodpi (URL) hachi nond gheun.",
+       "missing-article": "Totv-kox (Database) hantun mellunk zai aslem tem mozkur \"$1\" $2 mellunk-nam.\n\nHorxim, oxem ek pornem frk vo eka panachea itihasacho duvo kaddun uddoila, ten’na zata.\n\nOxem nhoi zalear, tuka software-ant chuk sampoddlea zait.\nUpkar korun eka [[Special:ListUsers/sysop|karbhari]]chea nodrek hadd, Ontorzalleant Zago Sodpi (URL) hachi nond ghevn.",
        "missingarticle-rev": "(uzollnni#: $1)",
        "missingarticle-diff": "(Frk: $1, $2)",
        "badtitle": "Chukichem nanv",
        "loginerror": "Sotrorombhachi truti",
        "createacct-error": "Khatem rochtanam truti",
        "createaccounterror": "Khatem rochunk zaunk na: $1",
-       "loginsuccesstitle": "Sotrorombh zalem",
+       "loginsuccesstitle": "Sotrarombh zalem",
        "nosuchusershort": "\"$1\" hea nanvan konn vapurpi na.\nNanv boroitana chuk zali gai?",
        "nouserspecified": "Vapurpeachem nanv diunk-uch zai.",
        "login-userblocked": "Hea vapurpeak addaila. Sotrorombh korunk zaina.",
        "emaildisabled": "Hi site mail dhadpak xokona.",
        "accountcreated": "Khatem rochlem.",
        "createaccount-title": "{{SITENAME}} -ak khatem rochlem",
-       "login-abort-generic": "Tujem sotrorombh opexi tharlam - Nixfolit",
+       "login-abort-generic": "Tujem sotrorombh opexi tharlam - Nixfollit",
        "login-migrated-generic": "Tujem khatem stholontrit zalam ani vapurpeachem nanv hea wikicher anink ostitvant na.",
        "loginlanguagelabel": "Bhas: $1",
        "pt-login": "Sotrorombh",
        "passwordreset-domain": "Domain:",
        "passwordreset-email": "Email potto:",
        "passwordreset-emailelement": "Vapurpeachem nanv: \n$1\n\nTatpurtem gupitutor: \n$2",
-       "passwordreset-emailsentemail": "Ho email pot'to tujea kontak zodlelem asa zalear, gupitutor portun tharaipacho email dhadlelem zatelem.",
-       "changeemail": "Email potto bodol vo kad",
+       "passwordreset-emailsentemail": "Ho email pot'to tujea hixobant zoddlolo asa zalear, gupitutor portun tharavpacho email dhaddlelem zatelem.",
+       "changeemail": "Email po’tto bodol vo kadd",
        "changeemail-oldemail": "Sodhyacho email potto:",
        "changeemail-newemail": "Novo email potto:",
        "changeemail-none": "(kai na)",
        "anoneditwarning": "<strong>Chotrai:</strong> Tuven sotrorombh korunk nai. Tu bodol korit zalear tuzo IP pot'to soglleank polleunk zatelem. Tu <strong>[$1 sotrorombh korit]</strong> vo <strong>[$2 kont rochit]</strong> zalear, tuje bodol tuzo vaporpeachem nanvak zoddteleo ani anik-ui faide asat.",
        "missingcommenttext": "Upkar korun tuzo xero boroi.",
        "blockedtitle": "Vapurpeak addaila",
-       "blockedtext": "<strong>Tujem vaporpeachem nanv vo IP pot'to addavpant aila.</strong>\n\nAddavop $1 hannem kelam.\nKaronn dilam tem <em>$2</em>.\n\n* Addavpachi survat: $8\n* Addavpachea somp’pacho vell: $6\n* Addavpak ievjila: $7\n\nTujean $1-ak vo dusrea [[{{MediaWiki:Grouppage-sysop}}|karbhariak]] addavnne bodol bhasabhas korunk sompork korunk zata. Tujean \"{{int:emailuser}}\" sobhavgunn vaprunk zaina kheriz ek void email pot'to tujea [[Special:Preferences|khatem posontint]] nischit kelea xivai ani tuka tem vaporpak addavnk na zalear. Tuzo chalont IP pot'to asa $3, ani addavnnecheo ank #$5 asa. Soglleo voileo bariksanno tum kortai tea vicharant somavex kor.",
+       "blockedtext": "<strong>Tujem vaporpeachem nanv vo IP pot'to addavpant aila.</strong>\n\nAddavop $1 hannem kelam.\nKaronn dilam tem <em>$2</em>.\n\n* Addavpachi survat: $8\n* Addavop sompovpacho vell: $6\n* Addavpak ievjila: $7\n\nTujean $1-ak vo dusrea [[{{MediaWiki:Grouppage-sysop}}|karbhariak]] addavnne vixim bhasabhas korunk sompork korunk zata. Tujean \"{{int:emailuser}}\" sobhavgunn vaprunk zaina kheriz ek void email pot'to tujea [[Special:Preferences|khatem posontint]] nischit kelea xivai ani tuka tem vaporpak addavnk na zalear. Tuzo chalont IP pot'to asa $3, ani addavnnecheo ank #$5 asa. Soglleo voileo bariksanno tum kortai tea vicharant somavex kor.",
        "blockednoreason": "Kainch karonn diunk na",
        "loginreqtitle": "Sotrorombh gorjechem",
        "loginreqlink": "sotrorombh kor",
        "accmailtitle": "Gupitutor dhaddlea",
        "newarticle": "(Novem)",
        "newarticletext": "Tuven ek duveche patlav kelai, zachem pan azun rochunk na.\nPan rochunk, khallchea chovkottan boroi (anik mahitik [$1 adar pan] polloi).\nTu hangasor chukin pavlai zalear tujea internet browser-achi <strong>Fatim</strong> vo <strong>Back</strong> butao dab.",
-       "anontalkpagetext": "----\n<em>Hem bhasabhasechem pan ek ninami vaporpeak zannem ozun ek khatem ugddunk na, vo to tem vaporna.</em>\nHea khatir amkam ankddeancho IP pot'to vaprunk podta taka vollkhunk.\nToslo IP pot'to sabar vaporpeamni vaprum ieta.\nTum zor ek ninami vaporpi asa ani tuka dista ki sombondit xere tuje vixim keleat, upkar korun [[Special:CreateAccount|ek khatem roch]] vo [[Special:UserLogin|log in]] fuddle guspop ninami vaporpeanchem tallunk.‎",
-       "noarticletext": "Sodheak hem pan rinte asa.\nTujean dusrea panani [[Special:Search/{{PAGENAME}}|hea panache nanv sodunk zata]], <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} sombondhi sotrani sodunk zata], vo [{{fullurl:{{FULLPAGENAME}}|action=edit}} hem pan rochunk zata]</span>.",
-       "noarticletext-nopermission": "Sodheak hem pan rinte asa.\nTujean dusrea panani [[Special:Search/{{PAGENAME}}|hea panache nanv sodunk zata]], vo <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} sombondhi sotrani sodunk zata], pun tuka hem pan rochunk porvangi na.",
+       "anontalkpagetext": "----\n<em>Hem bhasabhasechem pan ek ninami vaporpeak zannem ozun ek khatem ugddunk na, vo to tem vaporna.</em>\nHea khatir amkam ankddeancho IP pot'to vaprunk podta taka vollkhunk.\nToslo IP pot'to sabar vaporpeamni vaprum ieta.\nTum zor ek ninami vaporpi asa ani tuka dista ki tukam sombond naslele xere tuje vixim keleat, upkar korun [[Special:CreateAccount|ek khatem roch]] vo [[Special:UserLogin|sotrarombh kor]] fuddle guspop ninami vaporpeanchem tallunk.‎",
+       "noarticletext": "Sodheak hem pan ritem asa.\nTujean dusrea panani [[Special:Search/{{PAGENAME}}|hea panache nanv sodunk zata]], <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} sombondhi sotrani sodunk zata], vo [{{fullurl:{{FULLPAGENAME}}|action=edit}} hem pan rochunk zata]</span>.",
+       "noarticletext-nopermission": "Sodheak hem pan ritem asa.\nTujean dusrea panani [[Special:Search/{{PAGENAME}}|hea panache nanv sodunk zata]], vo <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} sombondhi sotrani sodunk zata], pun tuka hem pan rochunk porvangi na.",
        "userpage-userdoesnotexist-view": "\"$1\" hea vapurpeachea khateachi nondnni korunk na.",
-       "clearyourcache": "<strong>Note:</strong> Samball’llea uprant, tuka ghoddiek tujea browseracho cache koddsoravnk poddot bodol pollonvche khatir.\n* <strong>Firefox / Safari:</strong> <em>Shift</em> dhor <em>Reload</em> klik kortana, vo dam <em>Ctrl-F5</em> vo <em>Ctrl-R</em> (<em>⌘-R</em> Mac-acher)\n* <strong>Google Chrome:</strong> <em>Ctrl-Shift-R</em> dam (<em>⌘-Shift-R</em> eka Mac-acher)\n* <strong>Internet Explorer:</strong> <em>Ctrl</em> dhor <em>Refresh</em> klik kortana, vo dam <em>Ctrl-F5</em>\n* <strong>Opera:</strong> Hanga voch: <em>Menu → Settings</em> (<em>Opera → Preferences</em> Mac-acher) ani uprant <em>Privacy & security → Clear browsing data → Cached images and files</em>.‎",
+       "clearyourcache": "<strong>Chotrai:</strong> Samball’llea uprant, tuka ghoddiek tujea browseracho cache koddsoravnk poddot bodol pollonvche khatir.\n* <strong>Firefox / Safari:</strong> <em>Shift</em> dhor <em>Reload</em> klik kortana, vo dam <em>Ctrl-F5</em> vo <em>Ctrl-R</em> (<em>⌘-R</em> Mac-acher)\n* <strong>Google Chrome:</strong> <em>Ctrl-Shift-R</em> dam (<em>⌘-Shift-R</em> eka Mac-acher)\n* <strong>Internet Explorer:</strong> <em>Ctrl</em> dhor <em>Refresh</em> klik kortana, vo dam <em>Ctrl-F5</em>\n* <strong>Opera:</strong> Hanga voch: <em>Menu → Settings</em> (<em>Opera → Preferences</em> Mac-acher) ani uprant <em>Privacy & security → Clear browsing data → Cached images and files</em>.‎",
        "previewnote": "<strong>Hem fokot ek zholok mhonn ugddas dhor.</strong>\nTuje bodol azun sambhallun dovrunk nant!",
        "continue-editing": "Sompadon korpachea zagear voch",
        "editing": "Sompadon kortai: $1",
        "permissionserrors": "Porvangechi chuk",
        "permissionserrorstext-withaction": "$2, hem korpak tuka porvangi na, {{PLURAL:$1|hea karnnak lagon|hea karnnank lagun}}:",
        "recreate-moveddeleted-warn": "<strong>Xittkavnni: Tum ek pan porot rochtai jem fattim kadun udoilelem.<strong>\n\nPanacho sompadon korop sarkem zalear dhean di.\nPan kadoupachem ani halovpachem sotr, sovloti khatir hangasor dilelem asa:",
-       "moveddeleted-notice": "Hem pan kadun udoilelem asa.\nPanachea kadun udounechi, rakhpachi, ani hallovnechi sotr sondorba khatir sokoil dilea.",
+       "moveddeleted-notice": "Hem pan kaddun udoilelem asa.\nPanachem kaddun uddovpachem, rakhpachem, ani halovpachem sotr sondhorba khatir sokoil dila.",
        "content-model-wikitext": "wikimozkur",
        "content-model-text": "Sado mozkur",
        "post-expand-template-inclusion-warning": "<strong>Chotrai:</strong> Sancho zoddpacho akar chod vhodlem asa.\nThodde sache zoddchenant.",
        "page_last": "akhirchem",
        "histlegend": "Frk nivoddni: Jeo uzollneo tuka comparar korunk zai, tenche fudle ''radio'' butao petoi ani ''Enter'' nazalear khalcho butao dab.<br />\nVivron: <strong>({{int:cur}})</strong> = halinchi uzollnie borobor forok, <strong>({{int:last}})</strong> = adli uzollnie borobor forok, <strong>{{int:minoreditletter}}</strong> = dhaktem bodol.",
        "history-fieldset-title": "Uzollnneo chall",
-       "history-show-deleted": "Fokot uzollnni kadun udoilelem",
+       "history-show-deleted": "Fokot uzollnni kadun uddoilolem",
        "histfirst": "sogleavon adhlem",
        "histlast": "sogleavon novem",
        "history-feed-title": "Uzollnniancho itihas",
        "revdel-restore": "Disnnem bodol",
        "pagehist": "Panacho itihas",
        "mergehistory-reason": "Karonn:",
-       "mergelog": "Vilin korpacho sotr",
+       "mergelog": "Vilin korpachem sotr",
        "revertmerge": "Doxim kor",
        "history-title": "\"$1\" hachea uzollnnecho itihas",
        "difference-title": "\"$1\"-chea avrutint ontor",
        "editundo": "kel'lem portavchem",
        "diff-empty": "(Kaim forok na)‎",
        "diff-multi-sameuser": "(Heach vaporpean {{PLURAL:$1|kel'lo modlo ek bodol dakhounk na|kel'le modle $1 bodol dakhounk nan}})",
-       "diff-multi-otherusers": "({{PLURAL:$1|Ek modli uzollnni|$1 modleo uzollnneo}} {{PLURAL:$2|ek her vaporpi|$2 her vaporpi}}, hache vorvim dakhovnk na)‎",
+       "diff-multi-otherusers": "({{PLURAL:$2|Ek her vaporpea|$2 her vaporpeam}} vorvim {{PLURAL:$1|ek modli uzollnni|$1 modleo uzollnneo}} dakhovnk na)",
        "searchresults": "Sodache porinaman",
        "searchresults-title": "\"$1\" -khatir sodache porinaman",
        "prevn": "adlem {{PLURAL:$1|$1}}",
        "prefs-help-email": "Email potto sokticho na, pun tum gupitutor visroxi zalear gupitutor punorsthapon korunk email pottechi goroz podta.",
        "prefs-help-email-others": "Tujean dusreank tujea vapurpeacho panar vo bhasabhasache panar aslele eke email duve vorvim tuje xim sompork korunk diunk zata.\nDusre tuje xim sompork kortat tednam tuzo email potto tankam kollchenam.",
        "userrights-user-editname": "Ek vapurpeachem nanv ghal:",
-       "group-bot": "Robotam",
+       "group-bot": "Robottam",
        "group-sysop": "Karbhari",
        "group-all": "(soglle)",
        "grouppage-bot": "{{ns:project}}:Robotam",
        "right-move": "Panam haloi",
        "right-writeapi": "Borovpeache API-cho upeog",
        "newuserlogpage": "Vapurpi rochnnechem sotr",
-       "rightslog": "Vaporpeachea hokancho sotr",
+       "rightslog": "Vaporpeachea hokanchem sotr",
        "action-edit": "hem pan sudar",
        "action-createaccount": "hem vaporpeachem khatem roch",
        "nchanges": "$1 {{PLURAL:$1|bodol}}",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|nove pananchi suchi]]-ui polloi)",
        "rcfilters-tag-remove": "'$1' kadd",
        "rcfilters-legend-heading": "<strong>Sonkxepachi volleri:</strong>",
+       "rcfilters-group-results-by-page": "Pana pormonnem pongddache porinnam",
        "rcfilters-activefilters": "Kriaxil challnneo",
        "rcfilters-activefilters-hide": "Lipoi",
        "rcfilters-activefilters-show": "Dakhoi",
        "rcfilters-savedqueries-unsetdefault": "Default aslolem kaddun uddoi",
        "rcfilters-savedqueries-remove": "Kadun udoi",
        "rcfilters-savedqueries-new-name-label": "Nanv",
+       "rcfilters-savedqueries-new-name-placeholder": "Challnnecho hetu vornnon kor",
        "rcfilters-savedqueries-apply-label": "Challnni roch",
+       "rcfilters-savedqueries-apply-and-setdefault-label": "Default challnni roch",
        "rcfilters-savedqueries-cancel-label": "Rod'd kor",
+       "rcfilters-savedqueries-add-new-title": "Chalont challnnechi manddavoll samball",
+       "rcfilters-savedqueries-already-saved": "Heo challnneo adinch samball’lloleo asat. Ek novi Samball’lloli Challnni rochunk, tujeo manddavolleo bodol.",
        "rcfilters-restore-default-filters": "Default challnneo porot hadd",
        "rcfilters-clear-all-filters": "Soglleo challnneo nivoll kor",
        "rcfilters-show-new-changes": "$1 savn noveo bodol polloi",
        "rcfilters-filterlist-feedbacklink": "Hea challnnechea avtam vixim tuka kitem dista tem amkam sang",
        "rcfilters-highlightmenu-title": "Ek rong vinch",
        "rcfilters-filterlist-noresults": "Kosleoch challnneo mellunk nant",
+       "rcfilters-state-message-fullcoverage": "Hea pongddantle soglleo challnneo vinchop mhonnche kainch vinchop na, hea khatir he challnnek kainch porinnam na. Pongddant  hacho somavex asa: $1",
        "rcfilters-filtergroup-authorship": "Iogdanachem borovp",
        "rcfilters-filter-editsbyself-label": "Tuven kel'leo bodol",
        "rcfilters-filter-editsbyself-description": "Tujeo svotacheo yogdanam.",
        "rcfilters-filter-editsbyother-label": "Dusreanim kel'le bodol",
        "rcfilters-filter-editsbyother-description": "Tuje khas bhairavn, soglle bodol",
        "rcfilters-filtergroup-user-experience-level": "Vaporpeachi nondnni ani onnbhov",
+       "rcfilters-filter-user-experience-level-registered-label": "Nondnni kelolem",
+       "rcfilters-filter-user-experience-level-registered-description": "Sotrarombh zalole sompadok.",
+       "rcfilters-filter-user-experience-level-unregistered-label": "Nondnni korunk naslolem",
+       "rcfilters-filter-user-experience-level-unregistered-description": "Sompadok je sotrarombhit nant.",
        "rcfilters-filter-user-experience-level-learner-label": "Xikpi",
+       "rcfilters-filter-user-experience-level-learner-description": "Nondnni kelole sompadok zancho onnubhov \"Nove ievpi\" ani \"Onnbhovi vaporpi\" modem urta.",
+       "rcfilters-filter-user-experience-level-experienced-label": "Onnbhovi vaporpi",
+       "rcfilters-filter-user-experience-level-experienced-description": "500 odik sompadon ani 30 disanchem kario aslolem nondnni kelolem sompadok.",
        "rcfilters-filtergroup-automated": "Apoap zalolem iogdan",
        "rcfilters-filter-bots-label": "Robot",
        "rcfilters-filter-bots-description": "Apoap avtamni kelolem sompadon",
        "rcfilters-filter-humans-label": "Monxan kelolem (nhoi robotan)",
        "rcfilters-filter-humans-description": "Monxani kelolem sompadon",
-       "rcfilters-filter-reviewstatus-unpatrolled-description": "Paro kela mhonn khunnavnk naslolem sompadon.",
+       "rcfilters-filter-reviewstatus-unpatrolled-description": "Paro kela mhonn hatan vo apoap khunnavnk naslolem sompadon.",
        "rcfilters-filter-reviewstatus-unpatrolled-label": "Paro korunk naslolem",
+       "rcfilters-filter-reviewstatus-manual-description": "Sompadon zaka paro kelam mhonn hatan khunnailam.",
+       "rcfilters-filter-reviewstatus-manual-label": "Hatan paro korpant ailolem",
+       "rcfilters-filter-reviewstatus-auto-label": "Apoap paro korpant ailolem",
        "rcfilters-filtergroup-significance": "Mhotv",
        "rcfilters-filter-minor-label": "Dhakte bodol",
        "rcfilters-filter-minor-description": "Borovpean dhaktem mhonn khunne chitt kelolem sompadon",
        "rcfilters-filter-major-label": "Dhakte naslolem sompadon",
        "rcfilters-filter-major-description": "Dhaktem mhonn khunne chitt korunk naslolem sompadon",
        "rcfilters-filtergroup-watchlist": "Sadurvollerintlim panam",
-       "rcfilters-filter-watchlist-watchednew-description": "Bodol ghoddlea uprant tuvem bhett divnk na tea sadurvollerintlim panache bodol.",
+       "rcfilters-filter-watchlist-watched-label": "Sadurvollerintlim",
+       "rcfilters-filter-watchlist-watched-description": "Tujea Sadurvollerichea panamche bodol.",
+       "rcfilters-filter-watchlist-watchednew-label": "Sadurvolleriche nove bodol",
+       "rcfilters-filter-watchlist-watchednew-description": "Bodol ghoddleat ten’na savn tuvem bhett divnk nant tea sadurvollerintlim panache bodol.",
+       "rcfilters-filter-watchlist-notwatched-label": "Sadurvollerint na",
+       "rcfilters-filter-watchlist-notwatched-description": "Sadurvollerichim panank bodol soddun her sogllem.",
        "rcfilters-filtergroup-watchlistactivity": "Sadurvollerichem kario",
        "rcfilters-filter-watchlistactivity-unseen-label": "Pollovnk naslole bodol",
        "rcfilters-filter-watchlistactivity-unseen-description": "Bodol ghoddlea uprant tuvem bhett divnk na tea panache bodol.",
        "rcfilters-view-tags": "Khunnechittichem sompadon",
        "rcfilters-view-tags-tooltip": "Sompadonacheo khunne chitti vaprun porinnam chall",
        "rcfilters-view-tags-help-icon-tooltip": "Khunnechittichem sompadona babtint odik xikun ghe",
+       "rcfilters-liveupdates-button-title-off": "Nove bodol ghoddtta ten’na dakhol kor",
        "rcfilters-watchlist-markseen-button": "Soglle bodol polleleat mhonn khunnai.",
+       "rcfilters-watchlist-edit-watchlist-button": "Nodor dovorlolea panachi volleri sompadon kor",
        "rcfilters-watchlist-showupdated": "Bodol zal'leak savn je panank tuvem bhett dinvk na, te bodol <strong>datt</strong> okxoramni, ani ghott khunnamni dileat.",
+       "rcfilters-filter-showlinkedfrom-option-label": "Vinchlolea panant <strong>savn zulltat tim panam</strong>",
        "rcfilters-filter-showlinkedto-label": "Panak zoddtat tea panache bodol dakhoi",
+       "rcfilters-filter-showlinkedto-option-label": "Vinchlolea panak <strong>zulltat tim pana</strong>",
        "rcfilters-target-page-placeholder": "Ek panache nanv ( vo vorg) ghal",
        "rcnotefrom": "Sokoil <strong>$3, $4<strong> savn {{PLURAL:$5|zalelem bodol dilam|zalelem bodol dileant}} (<strong>$1<strong> meren {{PLURAL:$5|dakhoilam|dakhoileant}}).",
        "rclistfrom": "$3 $2 savn suru zatelim nove bodol dakhoi",
        "rcshowhidemine": "Mhoje bodol $1",
        "rcshowhidemine-show": "Dakhoi",
        "rcshowhidemine-hide": "Lipoi",
-       "rclinks": "Xevtiche $2 disanim zal'le $1 bodol dakhoi",
+       "rclinks": "Xevottche $2 disamni zal'le $1 bodol dakhoi",
        "diff": "frk",
        "hist": "iti",
        "hide": "Lipoi",
        "rc-change-size-new": "$1 {{PLURAL:$1|byte|byti}} bodol kel'lea uprant",
        "rc-enhanced-expand": "Bariksann dakhoi",
        "rc-enhanced-hide": "Bariksann lipoi",
-       "rc-old-title": "orombhant rochloli \"$1\" hea nanvan‎.",
+       "rc-old-title": "arombhant rochloli \"$1\" hea nanvan‎",
        "recentchangeslinked": "Sombondit bodol",
        "recentchangeslinked-feed": "Sombondit bodol",
        "recentchangeslinked-toolbox": "Sombondit bodol",
        "recentchangeslinked-title": "\"$1\"che sombondit bodol",
-       "recentchangeslinked-summary": "Eka panachem nanv boroi jea vorvim zoddlolea panancher vo panam pasun bodol  distolo. (Eka vorgonnache vangddi pollovnk, boroi {{ns:category}}:Vorgonnachem nanv). [[Special:Watchlist|Tujea sadurvollerint]] aslelim panacher bodol <strong>datt</strong> asat.",
+       "recentchangeslinked-summary": "Eka panachem nanv boroi jea vorvim zoddlolea panancher vo panam pasun bodol  distolo. (Eka vorgonnache vangddi pollovnk, boroi {{ns:category}}:Vorgonnachem nanv). [[Special:Watchlist|Tujea sadurvollerint]] aslolea panacher bodol <strong>datt</strong> asat.",
        "recentchangeslinked-page": "Panache nanv:",
        "recentchangeslinked-to": "Dil'em panache bodlek haka zodlelem panank kel'le bodol dakhoi",
        "upload": "Fayl upload kor",
        "filehist-comment": "Xero",
        "imagelinks": "Faylicho vapor",
        "linkstoimage": "{{PLURAL:$1|Hem pan|$1 Him panam}} hi fayl {{PLURAL:$1|vaporta|vaportat}}:",
-       "linkstoimage-more": "$1 poros odik {{PLURAL:$1|pan vaporta|panam vaporta}} hi fayl.\nSokoili volleri dakhoita {{PLURAL:$1|poilem pan|poilim $1 panam}} jem hich fayl vaporta. Ek [[Special:WhatLinksHere/$2|purnn volleri]] uplobdh asa.‎",
+       "linkstoimage-more": "$1 poros odik {{PLURAL:$1|pan vaporta|panam vaportat}} hi fayl.\nSokoili volleri dakhoita {{PLURAL:$1|poilem pan|poilim $1 panam}} jem hich fayl vaporta. Ek [[Special:WhatLinksHere/$2|purnn volleri]] uplobdh asa.‎",
        "nolinkstoimage": "Hea faylik vaportat toslim panam nant",
        "linkstoimage-redirect": "$1 (fayl punornirdexon) $2",
        "sharedupload-desc-here": "Hi fayl $1, hachi ani dusrea prokolpanim hachem upeog korunk zata.\nHachem [$2 faylichem vivron panan] asleli vivron khala dilea:",
        "longpages": "Lamb panam",
        "protectedpages-filters": "Challnneo:",
        "listusers": "Vaporpeanchi volleri",
-       "usercreated": "$3 hannem $1 disa $2 vaztam rochlelem",
+       "usercreated": "$3 hannem $1 disa $2 vorancher rochlolem",
        "newpages": "Novim panam",
        "move": "Zago bodol",
        "pager-newer-n": "{{PLURAL:$1|novem 1|novim $1}}",
        "specialloguserlabel": "Korpi:",
        "speciallogtitlelabel": "Mokh (mathallo vo {{ns:user}}:vapurpeachem nanv):",
        "log": "Sotram",
-       "all-logs-page": "Soglle bhousache sotram",
-       "alllogstext": "{{SITENAME}} hacheo sogllea uplobdh sotranchi ektthaim dakhovnni.\nTujean tuzo dekhavo ornum ieta ek sotracho prokar vinchun, vaporpeachem nanv (vhodle and dhakte okxora modem forok podta), vo porinnam zalolem pan (hanga-ui vhodle and dhakte okxora modem forok podta).‎",
+       "all-logs-page": "Sogllim bhousachim sotram",
+       "alllogstext": "{{SITENAME}} hacheo sogllea uplobdh sotranchi ektthaim dakhovnni.\nTujean tuzo dekhavo ornum ieta ek sotracho prokar vinchun, vaporpeachem nanv (vhoddlea ani dhakttea okxora modem forok poddtta), vo porinnam zalolem pan (hangai vhoddle and dhaktte okxora modem forok poddtta).",
        "logempty": "Sotran zullpi nog nant.‎",
        "allpages": "Sogllim panam",
        "nextpage": "Fuddlem pan ($1)",
        "allpagesfrom": "Hanga thavn suru zatelea panank dakhoi:",
        "allarticles": "Sogllim panam",
        "allpagessubmit": "Voch",
-       "allpages-hide-redirects": "Punornirdexonam lipoi",
+       "allpages-hide-redirects": "Punornirdexona lipoi",
        "categories": "Vorg",
        "sp-deletedcontributions-contribs": "iogdan",
        "linksearch-ns": "Nanv-tholl:",
        "watch": "Nodor dovor",
        "watchthispage": "Hea panar dixtt dovor",
        "unwatch": "Nodor kadd",
-       "watchlist-details": "Tujea Sadurvollerint {{PLURAL:$1|$1 pan asa|$1 panam asat}} (te-bhair ulovpachim panam asat).",
+       "watchlist-details": "Tujea Sadurvollerint {{PLURAL:$1|$1 pan asa|$1 panam asat}} (tea-bhair ulovpachim panam asat).",
        "wlheader-showupdated": "Tujea fatle bhette san bodol'lean tim panam '''datt''' dakhoileant.",
-       "wlnote": "Sokoil {{PLURAL:$1|ho nimanno bodol|hem nimanneo <strong>$1</strong> bodol}} nimannea {{PLURAL:$2|horan|<strong>$2</strong> horanim}}, $3, $4 porian.‎",
+       "wlnote": "Sokoil {{PLURAL:$1|ho nimanno bodol|hem nimanneo <strong>$1</strong> bodol}} nimannea {{PLURAL:$2|voran|<strong>$2</strong> voramni}}, $3, $4 porian.‎",
        "watchlist-options": "Sadurvollericheo poryay",
        "watching": "Disht dovortanv...",
        "unwatching": "Disht kaddthanv...",
        "linkshere": "Sokoilim panam <strong>$2</strong> ak zoddtat:",
        "nolinkshere": "Khoincheim pan <strong>$2</strong> ak zoddna.",
        "isredirect": "punornirdexon pan",
-       "istemplate": "Durasth-somaves",
+       "istemplate": "durasth-somaves",
        "isimage": "faylicho duvo",
        "whatlinkshere-prev": "{{PLURAL:$1|adlem|adlem $1}}",
        "whatlinkshere-next": "{{PLURAL:$1|fuddlem|fuddlim $1}}",
        "whatlinkshere-links": "← duve",
-       "whatlinkshere-hideredirs": "$1 punornirdexonam",
-       "whatlinkshere-hidetrans": "$1 durasth-somaveso",
+       "whatlinkshere-hideredirs": "$1 punornirdexona",
+       "whatlinkshere-hidetrans": "$1 durasth-somavex",
        "whatlinkshere-hidelinks": "$1 duve",
        "whatlinkshere-hideimages": "$1 faylinche duve",
        "whatlinkshere-filters": "Challnio",
        "change-blocklink": "Addavnnni bodol",
        "contribslink": "yogdan",
        "blocklogpage": "addavnnechem sotr",
-       "blocklogentry": "[[$1]] addailelem $2 asun vellacho ont: $3",
-       "reblock-logentry": "addavpachem bosovp bodol’lam [[$1]] hache khatir sompacho vell dilam $2 $3‎",
+       "blocklogentry": "[[$1]] ak addaila, itlea vellak: $2, karonn: $3",
+       "reblock-logentry": "addavpachem bosovp bodol’lam [[$1]] hache khatir sompovpacho vell dila $2 $3‎",
        "block-log-flags-nocreate": "Khatem rochop opatr kelam",
        "proxyblocker": "Protinidhi-sirvidor addavpi‎",
        "move-page": "$1 haloi",
        "allmessagesdefault": "Default sondex mozkur",
        "thumbnail-more": "Vhodlem kor",
        "thumbnail_error": "Lhan-imaz toiar kortana chuk zali. Karonn: $1",
-       "importlogpage": "Aiatacho sotr",
+       "importlogpage": "Aiatachem sotr",
        "tooltip-pt-userpage": "{{GENDER:|Tujem vaporpeachem}} pan",
        "tooltip-pt-mytalk": "{{GENDER:|Tumchem}} bhasabhasachem pan",
        "tooltip-pt-preferences": "{{GENDER:|Tumcheo}} avddi",
        "tooltip-ca-nstab-special": "Hem ek kherit pan, ani hem bodlunk zaina",
        "tooltip-ca-nstab-project": "Prokolpachem pan polloi",
        "tooltip-ca-nstab-image": "Faylichem pan polloi",
-       "tooltip-ca-nstab-mediawiki": "Iontronacho sondex polloi",
+       "tooltip-ca-nstab-mediawiki": "Iontronnacho sondex polloi",
        "tooltip-ca-nstab-template": "Sancho polloi",
        "tooltip-ca-nstab-category": "Vorgachem pan polloi",
        "tooltip-minoredit": "Haka ek kirkoll sudharop mhunn khunnay",
        "tooltip-rollback": "\"Kovllop\" hea panak nimannea yogdan korpean kello (kelle) bodol eka kollant portota.",
        "tooltip-undo": "\"Rodd' kor\" sudharop portita ani sudharopak Zholok ritin ukodta. Tem saran karon zoddunk dita.",
        "tooltip-summary": "Mottvo sar ghal",
-       "simpleantispam-label": "Spam-virudh topasni.\nHem bhori <strong>nakai</strong>!",
+       "simpleantispam-label": "Spam-virudh topasnni.\nHem bhor <strong>nakai</strong>!",
        "pageinfo-title": "\"$1\" ‎khatir mhaiti",
        "pageinfo-header-basic": "Mull mhaiti‎",
        "pageinfo-header-edits": "Bodolacho itihas",
        "pageinfo-header-properties": "Panache gunndhorm",
        "pageinfo-display-title": "Manddlolem mathallem",
        "pageinfo-default-sort": "Default arin manddunk chavi",
-       "pageinfo-length": "Panachi lambai (bayt-ant)‎",
+       "pageinfo-length": "Panachi lambai (baytt-ant)‎",
        "pageinfo-article-id": "Panacho ank",
        "pageinfo-language": "Panachea mozkurachi bhas",
        "pageinfo-content-model": "Panachea mozkuracho nomuno",
-       "pageinfo-robot-policy": "Robotam koddlean suchien ghalop",
+       "pageinfo-robot-policy": "Robotam koddlean suchent ghalop",
        "pageinfo-robot-index": "Porvangi asa",
        "pageinfo-robot-noindex": "Porvangi nam",
        "pageinfo-watchers": "Panacher dixtt dovortoleancho ankddo",
        "pageinfo-toolboxlink": "Panachi mahiti",
        "pageinfo-contentpage": "Ek mozkurachem pan koxem dhorpant ailam‎",
        "pageinfo-contentpage-yes": "Hoi",
-       "patrol-log-page": "Paro korpeacho sotr",
+       "patrol-log-page": "Paro korpachem sotr",
        "previousdiff": "←  Adlo bodol",
        "nextdiff": "Fuddlem bodol →",
        "widthheightpage": "$1 × $2, $3 {{PLURAL:$3|pan|panam}}",
        "redirect": "Fayl, vaporpi, pan, uzollnni vo sotr ank‎ vorvim punornirdexon kor",
        "redirect-summary": "Hem vixex pan punornirdexit korta eka faylik (faylichem nanv dilear), eke panak (uziollnecho ank vo panacho ank dilear), ek vaporpeachem panak (eke vaporpeache ank dilear), vo ek sotr nond (sotrachem ank dilear). Vapor: [[{{#Special:Redirect}}/file/Dekhik.jpg]], [[{{#Special:Redirect}}/page/64308]], [[{{#Special:Redirect}}/revision/328429]], [[{{#Special:Redirect}}/user/101]], vo [[{{#Special:Redirect}}/logid/186]].",
        "redirect-submit": "Voch‎",
-       "redirect-lookup": "Suchien polloi:",
+       "redirect-lookup": "Suchint polloi:",
        "redirect-value": "Mol:",
-       "redirect-user": "Vaporpeacho ank",
+       "redirect-user": "Vaporpeancho ank",
        "redirect-page": "Panacho ank",
        "redirect-revision": "Panachi uzollnni",
        "redirect-file": "Faylichem nanv",
        "htmlform-title-not-exists": "$1 ostitvant na.",
        "logentry-delete-delete": "$1, hannem {{GENDER:$2|kadun udoile}} pan $3",
        "logentry-delete-restore": "$1 hannem {{GENDER:$2|porot haddlam}} pan $3 ($4)‎",
-       "logentry-delete-revision": "$1 hannem {{PLURAL:$5|uzolliechem}} disnem  $3, hea panar {{GENDER:$2|bodol’la}}: $4‎",
+       "logentry-delete-revision": "$1 hannem {{PLURAL:$5|uzollnnechem}} disnnem $3, hea panar {{GENDER:$2|bodol’la}}: $4‎",
        "revdelete-content-hid": "mozkur lipoila",
        "logentry-move-move": "$1, hannem $3 panak $4 {{GENDER:$2|haloilea}}",
        "logentry-move-move-noredirect": "$1, hannem pan $3 savn $4 {{GENDER:$2|haloilam}} punornirdexon dorinastanam‎",
        "logentry-move-move_redir": "$1 hannem pan $3 savn $4 {{GENDER:$2|haloilolo}} punornirdexonavoir",
-       "logentry-patrol-patrol-auto": "$1-an $3, hea panachem $4, hea uzollniecho paro kelam mhonn apoap {{GENDER:$2|khunnailam}}.",
+       "logentry-patrol-patrol-auto": "$1-an $3, hea panachem $4, hea uzollnnecho paro kelam mhonn apoap {{GENDER:$2|khunnailam}}.",
        "logentry-newusers-create": "Vapurpeacho kont $1 {{GENDER:$2|rochlam}}",
        "logentry-newusers-autocreate": "Vaporpeachem khatem $1 apoap {{GENDER:$2|rochun}} ailem",
        "logentry-upload-upload": "$1-an $3 {{GENDER:$2|upload kela}}",
index 6480a93..85c86ad 100644 (file)
@@ -87,6 +87,7 @@
        "tog-useeditwarning": "הצגת אזהרה בעת עזיבת דף עריכה עם שינויים שטרם נשמרו",
        "tog-prefershttps": "תמיד להשתמש בתקשורת מאובטחת לאחר הכניסה לחשבון",
        "tog-showrollbackconfirmation": "הצגת הודעת אישור לאחר לחיצה על קישור \"שחזור\"",
+       "tog-requireemail": "דרישת דואר אלקטרוני כדי לאפס סיסמה",
        "underline-always": "תמיד",
        "underline-never": "לעולם לא",
        "underline-default": "ברירת המחדל של העיצוב או של הדפדפן",
        "content-model-css": "CSS",
        "content-json-empty-object": "אובייקט ריק",
        "content-json-empty-array": "מערך ריק",
-       "unsupported-content-model": "<strong>אזהרה:</strong> מודל התוכן $1 אינו נתמך בוויקי הזה.",
-       "unsupported-content-diff": "×\94ש×\95×\95×\90×\95ת ×\90×\99× ×\9f × ×ª×\9e×\9b×\95ת במודל התוכן $1.",
-       "unsupported-content-diff2": "×\94ש×\95×\95×\90×\95ת ×\91×\99×\9f ×\9e×\95×\93×\9c ×\94ת×\95×\9b×\9f $1 ×\9c×\91×\99×\9f ×\9e×\95×\93×\9c $2 ×\90×\99× ×\9f × ×ª×\9e×\9b×\95ת ×\91וויקי הזה.",
+       "unsupported-content-model": "<strong>×\90×\96×\94ר×\94:</strong> ×\9e×\95×\93×\9c ×\94ת×\95×\9b×\9f $1 ×\90×\99× ×\95 × ×ª×\9e×\9a ×\91×\90תר ×\94×\95×\95×\99ק×\99 ×\94×\96×\94.",
+       "unsupported-content-diff": "×\94ש×\95×\95×\90×\94 ×\91×\99×\9f ×\92רס×\90×\95ת ×\90×\99× ×\94 × ×ª×\9e×\9bת במודל התוכן $1.",
+       "unsupported-content-diff2": "×\94ש×\95×\95×\90×\94 ×\91×\99×\9f ×\92רס×\90×\95ת ×\9e×\9e×\95×\93×\9c ×\94ת×\95×\9b×\9f $1 ×\9c×\92רס×\90×\95ת ×\9e×\9e×\95×\93×\9c ×\94ת×\95×\9b×\9f $2 ×\90×\99× ×\94 × ×ª×\9e×\9bת ×\91×\90תר ×\94וויקי הזה.",
        "deprecated-self-close-category": "דפים שמשתמשים בתגיות HTML עם סגירה עצמית בלתי־תקינה",
        "deprecated-self-close-category-desc": "הדף מכיל תגיות HTML עם סגירה עצמית בלתי־תקינה, כגון <code dir=\"ltr\">&lt;b/></code> או <code dir=\"ltr\">&lt;span/></code>. ההתנהגות של תגיות אלה תשתנה בקרוב לצורך תאימות עם מפרט HTML5, ולכן יש להימנע משימוש בהן בקוד ויקי.",
        "duplicate-args-warning": "<strong>אזהרה:</strong> [[:$1]] קורא לדף [[:$2]] עם יותר מערך אחד עבור הפרמטר \"$3\". ייעשה שימוש רק בערך האחרון.",
        "undo-norev": "לא ניתן היה לבטל את העריכה כי היא אינה קיימת או כי היא נמחקה.",
        "undo-nochange": "נראה שהעריכה כבר בוטלה.",
        "undo-summary": "ביטול גרסה $1 של [[Special:Contributions/$2|$2]] ([[User talk:$2|שיחה]])",
+       "undo-summary-anon": "ביטול גרסה $1 של [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "ביטול גרסה $1 של משתמש מוסתר",
        "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>",
        "prefs-help-email": "כתובת דואר אלקטרוני היא אופציונלית, אבל היא חיונית לאיפוס הסיסמה במקרה ש{{GENDER:|תשכח|תשכחי}} אותה.",
        "prefs-help-email-others": "באפשרותך גם לאפשר למשתמשים ליצור איתך קשר באמצעות דוא\"ל דרך קישור בדף המשתמש או בדף השיחה שלך.\nכתובת הדוא\"ל שלך לא תיחשף כשמשתמשים יצרו איתך קשר.",
        "prefs-help-email-required": "כתובת דואר אלקטרוני נדרשת לכתיבה באתר.",
+       "prefs-help-requireemail": "אם אפשרות זו סומנה, האתר ישלח הודעת דוא\"ל המאפשרת את איפוס הסיסמה רק לאחר שמי שביקש אותה יספק גם את שם המשתמש וגם את כתובת הדוא\"ל של החשבון הזה.",
        "prefs-info": "מידע בסיסי",
        "prefs-i18n": "בינאום",
        "prefs-signature": "חתימה",
        "backend-fail-contenttype": "לא ניתן היה לקבוע את סוג התוכן של הקובץ לאחסון ב־\"$1\".",
        "backend-fail-batchsize": "למאגר אחסון הקבצים הפנימי הועבר אוסף של {{PLURAL:$1|פעולת קובץ אחת|$1 פעולות קובץ}}; המגבלה היא {{PLURAL:$2|פעולה אחת|$2 פעולות}}.",
        "backend-fail-usable": "קריאת או כתיבת הקובץ \"$1\" לא הצליחה כיוון שההרשאות אינן מספיקות או כיוון שהספריות/המכלים חסרים.",
-       "backend-fail-stat": "×\9c×\90 ×\94×\99×\94 ×\90פשר ×\9cקר×\95×\90 ×\90ת ×\94×\9eצ×\91 ×©×\9c ×\94ק×\95×\91×¥ \"$1\".",
-       "backend-fail-hash": "×\9c×\90 ×\94×\99×\94 ×\90פשר ×\9c×\94×\97×\9c×\99×\98 ×\9e×\94×\95 ×\92×\99×\91×\95×\91 ×\94×\94צפנ×\94 ×©×\9c ×\94ק×\95×\91×¥ \"$1\".",
+       "backend-fail-stat": "קר×\99×\90ת ×\9eצ×\91 ×\94ק×\95×\91×¥ \"$1\" ×\9c×\90 ×\94צ×\9c×\99×\97×\94.",
+       "backend-fail-hash": "×\9eצ×\99×\90ת ×¢×¨×\9a ×\94×\92×\99×\91×\95×\91 ×\94קר×\99פ×\98×\95×\92רפ×\99 ×©×\9c ×\94ק×\95×\91×¥ \"$1\" ×\9c×\90 ×\94צ×\9c×\99×\97×\94.",
        "filejournal-fail-dbconnect": "לא ניתן היה להתחבר לבסיס הנתונים של היומן עבור מאגר אחסון הקבצים הפנימי \"$1\".",
        "filejournal-fail-dbquery": "לא ניתן היה לעדכן את בסיס הנתונים של היומן עבור מאגר אחסון הקבצים הפנימי \"$1\".",
        "lockmanager-notlocked": "פתיחת הנעילה של \"$1\" לא הצליחה; הוא לא נעול.",
        "alreadyrolled": "לא ניתן לשחזר את העריכה של [[User:$2|$2]] ([[User talk:$2|שיחה]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) בדף [[:$1]];\nהדף כבר נערך או שוחזר.\n\nהעריכה האחרונה הייתה של [[User:$3|$3]] ([[User talk:$3|שיחה]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "תקציר העריכה היה: <em>$1</em>.",
        "revertpage": "שוחזר מעריכות של [[Special:Contributions/$2|$2]] ([[User talk:$2|שיחה]]) לעריכה האחרונה של [[User:$1|$1]]",
+       "revertpage-anon": "שוחזר מעריכות של [[Special:Contributions/$2|$2]] לעריכה האחרונה של [[User:$1|$1]]",
        "revertpage-nouser": "שוחזר מעריכות של משתמש מוסתר לעריכה האחרונה של {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "שוחזר מעריכות של {{GENDER:$3|$1}}\nלעריכה האחרונה של {{GENDER:$4|$2}}.",
        "sessionfailure-title": "בעיה בחיבור",
        "ipblocklist-legend": "מציאת משתמש חסום",
        "blocklist-userblocks": "הסתרת חסימות של משתמשים רשומים",
        "blocklist-tempblocks": "הסתרת חסימות זמניות",
+       "blocklist-indefblocks": "הסתרת חסימות בלתי מוגבלות בזמן",
        "blocklist-addressblocks": "הסתרת חסימות של כתובות IP בודדות",
        "blocklist-type": "סוג:",
        "blocklist-type-opt-all": "הכול",
index 94945ff..d04622a 100644 (file)
        "diff-multi-manyusers": "({{PLURAL:$1|Nije prikazana jedna međuinačica|Nisu prikazane $1 međuinačice|Nije prikazano $1 međuinačica}} više od {{PLURAL:$2|jednog|$2|$2}} suradnika)",
        "difference-missing-revision": "{{PLURAL:$2|Uređivanje|$2 uređivanja}} sljedeće šifre ($1) ne {{PLURAL:$2|postoji|postoje}}.\n\nOvo je obično uzrokovano kada kliknete na zastarjelu poveznicu na stranice koja je obrisana.\nViše informacija možete pronaći u [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} evidenciji brisanja].",
        "searchresults": "Rezultati pretrage",
+       "search-filter-title-prefix": "Pretraži samo stranice koje počinju prefiksom »$1«",
        "searchresults-title": "Rezultati pretrage za \"$1\"",
        "titlematches": "Pronađene stranice prema naslovu",
        "textmatches": "Pronađene stranice prema tekstu članka",
index e9ae01b..37106e5 100644 (file)
        "undo-norev": "A szerkesztés nem állítható vissza, mert nem létezik vagy törölve lett.",
        "undo-nochange": "A szerkesztés már vissza lett állítva.",
        "undo-summary": "Visszavontam [[Special:Contributions/$2|$2]] ([[User talk:$2|vita]]) szerkesztését (oldid: $1)",
+       "undo-summary-anon": "Visszavontam [[Special:Contributions/$2|$2]] szerkesztését (oldid: $1)",
        "undo-summary-username-hidden": "A rejtett felhasználó által végzett $1 változat visszavonása",
        "cantcreateaccount-text": "Erről az IP-címről ('''$1''') nem lehet regisztrálni, mert [[User:$3|$3]] blokkolta az alábbi indokkal:\n\n:''$2''",
        "cantcreateaccount-range-text": "A regisztrációt a(z) <strong>$1</strong> IP-címtartományban, amelybe a te IP-címed (<strong>$4</strong>) is tartozik, [[User:$3|$3]] blokkolta.\n\n$3 a következő indoklást adta: <em>$2</em>",
        "alreadyrolled": "[[:$1]] utolsó, [[User:$2|$2]] ([[User talk:$2|vita]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) általi szerkesztését nem lehet visszavonni:\nidőközben valaki már visszavonta vagy szerkesztette a lapot.\n\nAz utolsó szerkesztést [[User:$3|$3]] ([[User talk:$3|vita]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]) végezte.",
        "editcomment": "A szerkesztési összefoglaló <em>$1</em> volt.",
        "revertpage": "Visszaállítottam a lap korábbi változatát [[Special:Contributions/$2|$2]] ([[User talk:$2|vita]]) szerkesztéséről [[User:$1|$1]] szerkesztésére",
+       "revertpage-anon": "Visszaállítottam a lap korábbi változatát [[Special:Contributions/$2|$2]] szerkesztéséről [[User:$1|$1]] szerkesztésére",
        "revertpage-nouser": "Visszaállítottam a lap korábbi változatát (szerkesztőnév eltávolítva) szerkesztéséről [[User:$1|$1]] szerkesztésére",
        "rollback-success": "{{GENDER:$3|$1}} szerkesztéseit visszaállítottam {{GENDER:$4|$2}} utolsó változatára.",
        "sessionfailure-title": "Munkamenethiba",
index 1f35ef6..eb94cd0 100644 (file)
        "undo-main-slot-only": "Le modification non poteva esser disfacite perque illo implica contento foras del cannellatura principal.",
        "undo-norev": "Impossibile annullar le modification proque illo non existe o esseva delite.",
        "undo-nochange": "Pare que iste modification ha jam essite disfacite.",
-       "undo-summary": "Annullava le version $1 per [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussion]] | [[Special:Contributions/$2|{{MediaWiki:Contribslink}}]])",
+       "undo-summary": "Disfacite le version $1 per [[Special:Contributions/$2|$2]] ([[User talk:$2|discussion]])",
+       "undo-summary-anon": "Disfacite le version $1 per [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Disfacer le revision $1 facite per un usator celate",
        "cantcreateaccount-text": "Le creation de contos desde iste adresse IP ('''$1''') ha essite blocate per [[User:$3|$3]].\n\nLe motivo que $3 dava es ''$2''",
        "cantcreateaccount-range-text": "Le creation de contos ab le adresses IP in le intervallo <strong>$1</strong>, le qual include tu adresse IP (<strong>$4</strong>), ha essite blocate per [[User:$3|$3]].\n\nLe motivo fornite per $3 es <em>$2</em>",
        "cantrollback": "Impossibile revocar le modification;\nle ultime contributor es le sol autor de iste pagina.",
        "alreadyrolled": "Non pote revocar le ultime modification de [[:$1]] per [[User:$2|$2]] ([[User talk:$2|discussion]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);\nun altere persona ha ja modificate o revocate le pagina.\n\nLe ultime modification esseva facite per [[User:$3|$3]] ([[User talk:$3|discussion]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Le summario del modification esseva: <em>$1</em>.",
-       "revertpage": "Reverteva modificationes per [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussion]]) al ultime version per [[User:$1|$1]]",
+       "revertpage": "Reverteva modificationes per [[Special:Contributions/$2|$2]] ([[User talk:$2|discussion]]) al ultime version per [[User:$1|$1]]",
+       "revertpage-anon": "Reverteva modificationes per [[Special:Contributions/$2|$2]] al ultime version per [[User:$1|$1]]",
        "revertpage-nouser": "Reverteva modificationes per un usator celate al ultime version per {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Revocava modificationes per {{GENDER:$3|$1}};\nretornava al version per {{GENDER:$4|$2}}.",
        "sessionfailure-title": "Error de session",
index d394695..0ba4725 100644 (file)
        "nocreate-loggedin": "Anda tak memiliki hak akses untuk membuat halaman baru.",
        "sectioneditnotsupported-title": "Penyuntingan bagian tidak didukung",
        "sectioneditnotsupported-text": "Penyuntingan bagian tidak didukung di halaman sunting ini.",
+       "modeleditnotsupported-title": "Penyuntingan tidak didukung",
+       "modeleditnotsupported-text": "Penyuntingan tidak didukung untuk model konten $1.",
        "permissionserrors": "Kesalahan Hak Akses",
        "permissionserrorstext": "Anda tak memiliki hak untuk melakukan hal itu karena {{PLURAL:$1|alasan|alasan-alasan}} berikut:",
        "permissionserrorstext-withaction": "Anda tidak memiliki hak akses untuk $2, karena {{PLURAL:$1|alasan|alasan}} berikut:",
        "content-model-css": "CSS",
        "content-json-empty-object": "Objek kosong",
        "content-json-empty-array": "Larik kosong",
+       "unsupported-content-model": "<strong> Peringatan: </strong> Model konten $1 tidak didukung di wiki ini.",
+       "unsupported-content-diff": "Beda tidak didukung untuk model konten $1.",
+       "unsupported-content-diff2": "Perbedaan antara model konten $1 dan $2 tidak didukung di wiki ini.",
        "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.",
        "backend-fail-contenttype": "Tidak dapat menentukan tipe konten dari berkas yang disimpan di \"$1\".",
        "backend-fail-batchsize": "Penyimpanan backend diberikan batch $1 berkas {{PLURAL:$1||}}operasi; batasnya adalah $2 {{PLURAL:$2||}}operasi.",
        "backend-fail-usable": "Tidak dapat membaca atau menulis berkas \"$1\" karena izin tidak memadai atau direktori/kontainer hilang.",
+       "backend-fail-stat": "Tidak dapat membaca status berkas \"$1\".",
+       "backend-fail-hash": "Tidak dapat menentukan hash kriptografi berkas \"$1\".",
        "filejournal-fail-dbconnect": "Tidak dapat menyambung ke database jurnal untuk penyimpanan backend \"$1\".",
        "filejournal-fail-dbquery": "Tidak bisa update database jurnal untuk penyimpanan backend \"$1\".",
        "lockmanager-notlocked": "Tidak bisa membuka kunci \"$1\" karena \"$1\" tidak terkunci.",
        "sessionfailure": "Sepertinya ada masalah dengan sesi log Anda; log Anda telah dibatalkan sebagai antisipasi untuk mencegah pembajakan. Silakan tekan tombol \"kembali\" dan muat kembali halaman sebelum Anda masuk, lalu coba lagi.",
        "changecontentmodel": "Ubah model isi sebuah halaman",
        "changecontentmodel-legend": "Ubah model isi",
-       "changecontentmodel-title-label": "Judul halaman",
+       "changecontentmodel-title-label": "Judul halaman:",
        "changecontentmodel-current-label": "Model konten saat ini:",
-       "changecontentmodel-model-label": "Model konten baru",
+       "changecontentmodel-model-label": "Model konten baru:",
        "changecontentmodel-reason-label": "Alasan:",
        "changecontentmodel-submit": "Ubah",
        "changecontentmodel-success-title": "Model konten ini telah diubah",
        "move-page-legend": "Pindahkan halaman",
        "movepagetext": "Menggunakan formulir di bawah ini akan mengubah nama suatu halaman dan memindahkan semua data sejarah ke nama baru.\nJudul lama akan menjadi halaman pengalihan ke judul baru.\nAnda dapat memperbarui pengalihan yang menuju ke judul asli secara otomatis.\nJika Anda memilih tidak, pastikan untuk memeriksa\n[[Special:DoubleRedirects|pengalihan ganda]] atau [[Special:BrokenRedirects|pengalihan rusak]].\nAnda bertanggung jawab untuk memastikan bahwa pranala terhubung ke tempat seharusnya.\n\nPerhatikan bahwa halaman '''tidak''' akan dipindah apabila telah ada halaman pada judul yang baru, kecuali bila halaman peralihan dan tidak mempunyai sejarah penyuntingan. \nIni berarti Anda dapat mengubah kembali nama halaman seperti semula apabila Anda membuat kesalahan, dan Anda tidak dapat menimpa halaman yang telah ada.\n\n'''Catatan:'''\nIni dapat mengakibatkan perubahan drastis dan tak terduga bagi halaman yang populer; pastikan Anda mengerti konsekuensinya sebelum melanjutkan.",
        "movepagetext-noredirectfixer": "Formulir di bawah ini digunakan untuk mengubah nama suatu halaman dan memindahkan semua data sejarah ke nama baru.\nJudul yang lama akan menjadi halaman peralihan menuju judul yang baru.\nPastikan untuk memeriksa pengalihan [[Special:DoubleRedirects|ganda]] atau [[Special:BrokenRedirects|rusak]].\nAnda bertanggung jawab untuk memastikan bahwa pranala terus menyambung ke halaman yang seharusnya.\n\nPerhatikan bahwa halaman '''tidak''' akan dipindah apabila telah ada halaman yang menggunakan judul yang baru, kecuali bila halaman tersebut kosong atau merupakan halaman peralihan dan tidak mempunyai sejarah penyuntingan.\nIni berarti Anda dapat mengubah nama halaman kembali seperti semula apabila Anda membuat kesalahan, dan Anda tidak dapat menimpa halaman yang telah ada.\n\n'''Catatan:'''\nHal ini dapat mengakibatkan perubahan yang tak terduga dan drastis bagi halaman yang populer;\nPastikan Anda mengerti konsekuensi dari perbuatan ini sebelum melanjutkan.",
+       "movepagetext-noredirectsupport": "Menggunakan formulir di bawah ini akan mengubah nama halaman, memindahkan semua riwayatnya ke nama baru.\nAnda bertanggung jawab untuk memastikan bahwa pranala akan mengarah kemana seharusnya.\n\nPerhatikan bahwa halaman tersebut <strong> tidak </strong> akan dipindahkan jika sudah ada halaman di judul baru.\nIni berarti bahwa Anda dapat mengganti nama halaman kembali ke tempat namanya diubah jika Anda melakukan kesalahan, dan Anda tidak dapat menimpa halaman yang sudah ada.\n\n<strong> Catatan: </strong>\nIni bisa menjadi perubahan drastis dan tidak terduga untuk halaman populer;\npastikan Anda memahami konsekuensinya sebelum melanjutkan.",
        "movepagetalktext": "Jika Anda mencentang kotak ini, halaman pembicaraan berkaitan akan dipindahkan secara otomatis ke judul baru, kecuali halaman pembicaraan tersebut tidak kosong.\n\nDalam kasus tersebut, Anda harus memindahkan atau menggabungkan halaman secara manual.",
        "moveuserpage-warning": "'''Peringatan:''' Anda tengah memindahkan halaman pengguna. Perlu diketahui bahwa hanya halaman yang akan dipindahkan namun pengguna ''tidak akan'' berganti nama.",
        "movecategorypage-warning": "<strong>Peringatan:</strong> Anda akan memindahkan halaman kategori. Perlu diketahui bahwa hanya halaman yang akan dipindahkan dan setiap halaman dalam kategori lama <em>tidak</em> akan dikategorikan ulang ke yang baru.",
        "delete_and_move_reason": "Dihapus untuk mengantisipasikan pemindahan halaman dari \"[[$1]]\"",
        "selfmove": "Tidak dapat memindahkan halaman, karena judul sumber dan judul tujuan sama.",
        "immobile-source-namespace": "Tidak dapat memindahkan halaman dalam ruang nama \"$1\"",
+       "immobile-source-namespace-iw": "Halaman pada wiki lain tidak dapat dipindahkan dari wiki ini.",
        "immobile-target-namespace": "Tidak dapat memindahkan halaman ke ruang nama \"$1\"",
        "immobile-target-namespace-iw": "Pranala interwiki bukanlah target yang valid untuk pemindahan halaman.",
        "immobile-source-page": "Halaman ini tidak dapat dipindahkan.",
        "immobile-target-page": "Tidak dapat memindahkan ke judul tujuan tersebut.",
+       "movepage-invalid-target-title": "Nama yang diminta tidak valid.",
        "bad-target-model": "Tujuan yang diinginkan menggunakan model konten yang berbeda. Tidak dapat mengkonversi dari  $1  untuk  $2 .",
        "imagenocrossnamespace": "Tidak dapat memindahkan berkas ke ruang nama non-berkas",
        "nonfile-cannot-move-to-file": "Tidak dapat memindahkan non-berkas ke ruang nama berkas",
        "common.json": "/* JSON apa pun yang ada di sini akan dimuat untuk semua pengguna ketika memuat semua halaman. */",
        "common.js": "/* JavaScript yang ada di sini akan diterapkan untuk semua kulit. */",
        "group-autoconfirmed.js": "/* Semua JavaScript di sini hanya dimuatkan untuk pengguna terkonfirmasi otomatis */",
+       "group-user.js": "/* Semua Skrip Java di sini hanya dimuatkan untuk pengguna terdaftar saja */",
        "group-bot.js": "/* Semua JavaScript di sini hanya dimuatkan untuk bot */",
        "group-sysop.js": "/* Semua JavaScript di sini hanya dimuatkan untuk pengurus */",
        "group-bureaucrat.js": "/* Semua JavaScript di sini hanya dimuatkan untuk birokrat */",
        "log-name-pagelang": "Log perubahan bahasa",
        "log-description-pagelang": "Ini adalah log perubahan dalam bahasa halaman.",
        "logentry-pagelang-pagelang": "$1 {{GENDER:$2|mengubah}} bahasa $3 dari $4 menjadi $5.",
+       "default-skin-not-found": "Aduh! Kulit baku untuk wiki Anda, didefinisikan dalam <code dir=\"ltr\">$wgDefaultSkin</code> sebagai <code>$1</code>, tidak tersedia.\n\nInstalasi Anda tampaknya menyertakan {{PLURAL:$4|kulit}} berikut ini. Lihat [https://www.mediawiki.org/wiki/Manual:Skin_configuration manual konfigurasi kulit] untuk informasi cara mengaktifkannya {{PLURAL:$4|dan pilih yang baku}}.\n\n$2\n\n; Jika Anda baru saja menginstal MediaWiki:\n: Anda mungkin menginstal dari git, atau langsung dari kode sumber menggunakan beberapa metode. Ini diharapkan. Coba pasang beberapa kulit dari [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's direktori kulit], dengan:\n: * Mengunduh [https://www.mediawiki.org/wiki/Download tarbal instaler], yang dilengkapi dengan beberapa kulit dan ekstensi. Anda dapat salin tempel direktori <code>kulit/</code> darinya.\n: * Mengunduh tarbal kulit individual dari [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n: * [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Menggunakan Git untuk mengunduh kulit].\n: Melakukan ini seharusnya tidak mengganggu repositori git Anda jika Anda seorang pengembang MediaWiki.\n\n; Jika Anda baru saja upgrade MediaWiki:\n: MediaWiki 1.24 dan yang lebih baru tidak lagi secara otomatis mengaktifkan kulit yang diinstal (lihat [https://www.mediawiki.org/wiki/Manual:Skin_autodiscovery Manual kulit autodiscovery]). Anda dapat paste {{PLURAL:$5|baris}} berikut ke <code> LocalSettings.php</code> untuk mengaktifkan {{PLURAL:$5|semua}} {{PLURAL:$5|kulit}} yang terinstal:\n\n<pre dir=\"ltr\">$3</pre>\n\n; Jika Anda baru saja memodifikasi <code>LocalSettings.php</code>:\n: Periksa ulang mana tahi salah ketik.",
+       "default-skin-not-found-no-skins": "Aduh! Kulit baku untuk wiki Anda, didefinisikan dalam <code dir=\"ltr\">$wgDefaultSkin</code> sebagai <code>$1</code>, tidak tersedia.\n\nAnda tidak memiliki skin yang terpasang.\n\n; Jika Anda baru saja menginstal MediaWiki:\n: Anda mungkin menginstal dari git, atau langsung dari kode sumber menggunakan beberapa metode. Ini diharapkan. Coba pasang beberapa kulit dari [https://www.mediawiki.org/wiki/Category:All_skins mediawiki.org's direktori kulit], dengan:\n: * Mengunduh [https://www.mediawiki.org/wiki/Download tarbal instaler], yang dilengkapi dengan beberapa kulit dan ekstensi. Anda dapat salin tempel direktori <code>kulit/</code> darinya.\n: * Mengunduh tarbal kulit individual dari [https://www.mediawiki.org/wiki/Special:SkinDistributor mediawiki.org].\n: * [https://www.mediawiki.org/wiki/Download_from_Git#Using_Git_to_download_MediaWiki_skins Menggunakan Git untuk mengunduh kulit].\n: Melakukan ini seharusnya tidak mengganggu repositori git Anda jika Anda seorang pengembang MediaWiki. Lihat [https://www.mediawiki.org/wiki/Manual:Skin_configuration Manual: Konfigurasi kulit] untuk informasi cara mengaktifkan kulit dan pilihan baku.",
        "default-skin-not-found-row-enabled": "* <code>$1</code> / $2 (aktif)",
        "default-skin-not-found-row-disabled": "* <code>$1</code> / $2 (<strong>nonaktif</strong>)",
        "mediastatistics": "Statistik media",
index 81ade2a..d8070a0 100644 (file)
        "diff-empty": "(Nula difero)",
        "diff-multi-sameuser": "(ne montresas {{PLURAL:$1|1 meza revizo|$1 meza revizi}} facita da la sama uzero)",
        "diff-multi-otherusers": "(ne montresas {{PLURAL:$1|1 intermeza revizo|$1 intermeza revizi}} facita da {{PLURAL:$2|altra uzero|$2 altra uzeri}})",
+       "difference-missing-revision": "{{PLURAL:$2|Un revizo|$2 revizi}} de ca difero ($1) ne trovesis.\n\nTo ordinare eventas kande vu sequas obsoleta ligilo a pagino eliminata.\nVu povas vidar detali en la 'log' [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}}, pri efacinda pagini].",
        "searchresults": "Rezultaji dil sercho",
        "search-filter-title-prefix-reset": "Traserchar pagini",
        "searchresults-title": "Sercho-rezultaji por \"$1\"",
        "unusedimages": "Neuzata imaji",
        "wantedcategories": "Dezirata kategorii",
        "wantedpages": "Dezirata pagini",
+       "wantedpages-summary": "Listo pri neexistanta pagini, organizata segun la quanto di ligili a li, ecepte pagini qui nur havas ridirekti a li. Por kompleta listo pri neexistanta pagini, videz la [[{{#special:BrokenRedirects}}|listo pri ruptita ligili]].",
        "wantedfiles": "Dezirata arkivi",
        "wantedtemplates": "Dezirata shabloni",
        "mostcategories": "Pagini maxime kategorizita",
        "movepagetext": "Uzante ica formularo onu povas rinomizar pagino, movante olua omna versionaro ad la nova titulo.\nLa antea titulo konvertesos a ridirektilo a la nova titulo.\nLa ligili a la antea titulo dil pagino ne chanjesos.\nVoluntez certigar ke ne esas [[Special:DoubleRedirects|duopla]] o [[Special:BrokenRedirects|ruptota ridirektili]].\nVu responsas ke la ligili duros direktante a la pagino korespondanta.\n\nMemorez ke la pagino '''ne''' rinomizesos se ja existus pagino kun la nova titulo, eceptuante ke la pagino esas vakua o ridirektilo sen versionaro.\nIco signifikas ke vu povos rinomizar pagino a olua originala titulo se eroras skribante la nova titulo, ma ne povos riskribar existanta pagino.\n\n'''EGARDEZ!'''\nIca povas esar drastika chanjo e ne-esperinda por populara pagino;\nvoluntez certigar ke vu komprenas la konsequi qui eventos ante durar adavane.",
        "movepagetext-noredirectfixer": "Uzar la formulario infre rinomizos la pagino, e tota lua historio-listo a la nova nomo.\nL'anciena titulo ridirektesos a la nova titulo.\nVerifikez la [[Special:DoubleRedirects|duopla]] e/o la [[Special:BrokenRedirects|krevita ridirekti]].\n<strong>Esas vua responso verifikar se omna ligili esas korekta.</strong>\n\nVidez ke la pagino <strong>ne rinomizesos se existar pagino kun la sama titulo</strong>, ecepte se ol ridirektesas a la prezenta pagino e ne havas pasinta historio pri redaktado.\nTo signifikas ke vu povas retroe rinomizar pagino a lua antea nomo se ol rinomizesis erore, e ke vu ne povas supresar existanta pagino per ridirektado di altra pagino.\n\n<strong>Atencez:</strong>\nLa rinomizo povas esar drastika chanjo por pagini qui esas populara;\nhavez klara certezo pri la konsequi di la posibla rinomizo di la pagino, ante facar ol!",
        "movepagetalktext": "Se vu markizos ca buxo, la diskuto-pagino asociita anke modifikesos a la nova titulo, ecepte se diskuto-pagino nevakua ja existar ibe.\n\nCakaze, vu propra mustos movar la diskuto-pagino o mixar la du texti, se vu deziros.",
-       "movecategorypage-warning": "<strong>Atencez:</strong> Vu balde rinomizos pagino di \"KATEGORIO\". Nur la titulo di la kategorio chanjesos, ma <em>nula pagino kategoriizita segun l'anciena kategorio</em> modifikesos automatale por la nova kategorio.",
+       "movecategorypage-warning": "<strong>Atencez:</strong> Vu balde rinomizos pagino pri \"KATEGORIO\". Nur la titulo di la kategorio chanjesos, ma <em>nula pagino kategoriizita segun l'anciena kategorio</em> modifikesos automatale por la nova kategorio.",
        "movenologintext": "Vu mustas esar registragita uzero ed [[Special:UserLogin|enirir]] por rinomizar pagino.",
        "newtitle": "Nova titulo:",
        "move-watch": "Surveyar ca pagino",
        "fileduplicatesearch-filename": "Nomo dil arkivo:",
        "fileduplicatesearch-submit": "Serchar",
        "specialpages": "Specala pagini",
+       "specialpages-note-top": "Surskriburo",
        "specialpages-group-maintenance": "Raporti pri manteno",
        "specialpages-group-other": "Altra specala pagini",
        "specialpages-group-login": "Enirar / krear konto",
index 8d7fdc1..8bd7bc0 100644 (file)
        "sessionfailure": "ログインのセッションに問題が発生しました。\nセッション乗っ取りを防ぐため、操作を取り消しました。\nフォームを再送信してください。",
        "changecontentmodel": "ページのコンテンツ・モデルの変更",
        "changecontentmodel-legend": "コンテンツモデルを変更",
-       "changecontentmodel-title-label": "ページ名",
+       "changecontentmodel-title-label": "ページ名:",
        "changecontentmodel-current-label": "現在のコンテンツモデル",
-       "changecontentmodel-model-label": "新しい コンテンツ モデル",
+       "changecontentmodel-model-label": "新しい コンテンツ モデル:",
        "changecontentmodel-reason-label": "理由:",
        "changecontentmodel-submit": "変更",
        "changecontentmodel-success-title": "コンテンツ・モデルは変更されました",
index 243c68c..9a6d447 100644 (file)
        "feedback-cancel": "Wurung",
        "feedback-close": "Rampung",
        "feedback-external-bug-report-button": "Kirim ayahan tèhnis",
-       "feedback-dialog-title": "Awèh saran",
+       "feedback-dialog-title": "Kirimi pamrayoga",
        "feedback-error1": "Masalah: Kasil ora dingertèni saka API",
        "feedback-error2": "Masalah: Besutané wurung",
        "feedback-error3": "Masalah: Ora ana tanggepan saka API",
index ffdeba8..94aeafd 100644 (file)
        "prefs-watchlist-edits": "კონტროლის სიაში საჩვენებელი ცვლილებების მაქსიმალური რაოდენობა:",
        "prefs-watchlist-edits-max": "მაქსიმალური რაოდენობა: 1000",
        "prefs-watchlist-token": "კონტროლის სიის ტოკენი:",
+       "prefs-watchlist-managetokens": "ტოკენების მართვა",
        "prefs-misc": "სხვადასხვა",
        "prefs-resetpass": "შეცვალეთ პაროლი",
        "prefs-changeemail": "ელ-ფოსტის მისამართის შეცვლა ან წაშლა",
index 736037e..7310bd3 100644 (file)
        "morenotlisted": "ھیہ فہرست مکمل نو۔",
        "mypage": "مہ صفحہ",
        "mytalk": "مہ مشقولگی",
-       "anontalk": "بچے لو IP ھیہ",
+       "anontalk": "مشقولگی",
        "navigation": "رہنمائی",
        "and": "&#32;وا",
        "faq": "عام معلومات",
        "searcharticle": "Go/بوغے",
        "history": "تاریخچہ ء صفحہ",
        "history_short": "تاریخچہ",
-       "updatedmarker": "مہ آخری گیکا پت نوغ",
+       "history_small": "تاریخچہ",
+       "updatedmarker": "تہ آخری گیکا پت نوغ",
        "printableversion": "قابل طبع نسخہ",
        "permalink": "مستقل لنک",
        "print": "طباعت",
        "talk": "تبادلۂ خیال",
        "views": "خیالات",
        "toolbox": "ٹول بکس",
+       "tool-link-userrights": "حلقہ ہائے {{GENDER:$1|صارف}}ہ تبدیلی",
+       "tool-link-userrights-readonly": "{{GENDER:$1|صارف}} و گروہان لوڑے",
+       "tool-link-emailuser": "ھیہ {{GENDER:$1|صارف}}وت ای میل/بشلی کغاز انزاوے",
        "imagepage": "ھوٹوو صفحو لوڑے",
        "mediawikipage": "پیغامو صفحہو لوڑے",
        "templatepage": "سانچو صفحہو لوڑے",
        "jumptonavigation": "رہنمائی",
        "jumptosearch": "تلاش",
        "view-pool-error": "معذرت: تمام سرورا موجودہ وختہ اِضافی بوجھ شیر.\nبو زیادہ صارفین موجودہ وختہ ھیہ صفحو لاڑینیان \nبرائے مہربانی! صفحو لوڑیکو بچے دوبارہ کوشش کوریکاری پروشٹی پھوکرو انتظار کورے.\n\n$1",
-       "generic-pool-error": "معذرت: تمام سرورا موجودہ وختہ اِضافی بوجھ شیر.\nبو زیادہ صارفین موجودہ وختہ ھیہ صفحو لاڑینیان \nبرائے مہربانی! صفحو لوڑیکو بچے دوبارہ کوشش کوریکاری پروشٹی پھوکرو انتظار کورے.\n\n$1",
+       "generic-pool-error": "معذرت: تمام سرورا موجودہ وختہ اِضافی بوجھ شیر.\nبو زیادہ صارفین موجودہ وختہ ھیہ صفحو لاڑینیان \nبرائے مہربانی! صفحو لوڑیکو بچے دوبارہ کوشش کوریکاری پروشٹی پھوکرو انتظار کورے\n\n$1",
+       "pool-timeout": "مقفل کوریکو بچے انتظارو مہلت ختم",
+       "pool-queuefull": "قطار لیگی شیر",
        "pool-errorunknown": "نامعلوم خطا",
+       "pool-servererror": "پول اݰماریکو خدمت دستیاب نیکی ($1)۔",
        "poolcounter-usage-error": "استعمالہ خامی: $1",
        "aboutsite": "تعارف {{SITENAME}}",
        "aboutpage": "Project:کھوار ویکیپیڈیو تعارف",
        "pagetitle-view-mainpage": "{{SITENAME}}",
        "retrievedfrom": "‘‘$1’’ نقل کاردو",
        "youhavenewmessages": "تہ بچے ای $1 شیر۔ ($2)",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|آپ کے لیے}} {{PLURAL:$3|کسی دوسرے صارف|$3 صارفین}} کی جانب سے $1 ($2)۔",
+       "youhavenewmessagesmanyusers": "تہ بچے متعدد صارفینان وولٹیاری $1 ($2)۔",
        "newmessageslinkplural": "{{PLURAL:$1|نوغ پیغام|999=نوغ پیغاماتs}}",
        "newmessagesdifflinkplural": "آخری {{PLURAL:$1|تبدیلی|تبدیلی}}",
        "youhavenewmessagesmulti": "ء$1 تہ بچے نوغ نوغ پیغامات شینی",
        "databaseerror-text": "ڈیٹا بیس کیوریا خامی پیدا بیتی شیر.\nھیہ سافٹ ویئراای مسئلہ (بگ)و نشاندیکو بوس.",
        "databaseerror-textcl": "ڈیٹا بیس کیوریا خامی پیدا بیتی شیر.",
        "databaseerror-query": "کیوری: $1",
-       "databaseerror-function": "فنکشن: $ 1",
-       "databaseerror-error": "خرابی: $ 1",
+       "databaseerror-function": "فنکشن:$ 1",
+       "databaseerror-error": "نقص: $1",
        "laggedslavemode": "Warning: Page may not contain recent updates.\nخبردار: منکھن شیر کہ صفحہا موجودہ بتاریخہ جات شامل نو بونی",
        "readonly": "ڈیٹابیسا قلف لیگی شیر",
        "enterlockreason": "قلفو بچے کیہ وجہ درج کورے، بشمولِ تخمینہ کہ قلفو کیاوت کھولاو کورونو بوئے",
        "missingarticle-rev": "(نظرثانی#: $1)",
        "missingarticle-diff": "(مختلفات: $1, $2)",
        "readonly_lag": "ڈیٹابیس خودکار طورا قلف کورونو بیتی شیر تاکہ ماتحت ڈیٹابیسی معیلاتن درجہ آقو بوئے",
+       "nonwrite-api-promise-error": "ایچ ٹی ٹی پی سرنامہ 'Promise-Non-Write-API-Action' بھیجا گیا لیکن یہ ایک اے پی آئی نویس ماڈیول کو بھیجی گئی درخواست تھی۔",
        "internalerror": "خطائے اندرونی",
        "internalerror_info": "خطائے اندرونی: $1",
+       "internalerror-fatal-exception": "\"$1\" قسمو تباہ کن استثنا",
        "filecopyerror": "\"$1\" مسلو \"$2\" نقل کورونو نو ھوی",
        "filerenameerror": "مسلو \"$1\" و \"$2\" خور نم دیونو نو ھوی",
        "filedeleteerror": "مسلو \"$1\" حذف کورونو نو ھوی",
        "delete-hook-aborted": "حذف شدگی روکا کورونو ہوئے\nوضاحت کورونو نو ہوئے",
        "badtitle": "خراب عنوان",
        "badtitletext": "'درخاس شدہ صفحہو عنوان ناقص، خالی، یا کیہ غلط ربط شدہ بین لسانی یا بین ویکی عنوان شیر.\nشاید ھیارا ای یا زیات ھݰ حروف موجود شینی کہ ھیت عنوانا استعمال نو بونیان.',",
+       "title-invalid-empty": "درخواست شدہ عنوان خالی شیر یا ھیرا محض نام فضاو نام شیر۔",
+       "title-invalid-utf8": "درخواست شدہ عنوانہ نادرست یونیکوڈ حروف موجود شینی۔",
        "perfcached": "ذیلی ڈیٹا ابطن شدہ شیر وا ھمو بیکا امکان شیر A maximum of {{PLURAL:$1|one result is|$1 results are}} available in the cache.",
        "perfcachedts": "ذیلی ڈیٹا ابطن شدہ شیر وا آخری بار ھمو بتاریخیت $1 کورونو ہوئے. A maximum of {{PLURAL:$4|one result is|$4 results are}} available in the cache.",
        "querypage-no-updates": "ھیہ صفحہو بچے بتاریخات فی الحال ناقابل ساوزینو بیتی شینی. \nھمو ڈیٹا ھنیسے تازہ کورونو نو بوئے",
        "viewsource": "مسودو لوڑے",
        "viewsource-title": "$1 و مسودو لوڑے",
+       "actionthrottled": "Action throttled",
        "actionthrottledtext": "بطورِ ای ضدسپم تدبیر، تہ مختصار وختہ کئی دفعہ ھیہ کورومو کوریکو وجھین محدود کورونو ہوئے، وا تو ھیہ حدو پار کوری آسوس.\nبراہِ کرم، ای کما میلیٹ آچہ کھوشش کورے",
        "protectedpagetext": "ھیہ صفحہو تدویناری محفوظ لاکھیکو بچے قلف لیگینو بیتی شیر",
        "viewsourcetext": "تو صرف مضمونو لوڑیکو بوس وا ھو نقل کوریکو بوس:",
        "translateinterface": "تمام ویکیپیڈا تبدیلی یا شامل کوریکو بچے، ھمو استعمال کورے [https://translatewiki.net/ translatewiki.net]، میڈیا ویکی دارالترجمہ.",
        "namespaceprotected": "\"تتے '''$1''' فضائے نامہ صفحاتن تدوینو کوریکو اِجازت نیکی.\",",
        "mycustomcssprotected": "تے ھیہ سی ایس ایس (CSS) صفحہا ترمیم کوریکو اختیار نیکی۔",
+       "mycustomjsonprotected": "تتے ھیہ سی ایس ایس (CSS) صفحہا ترمیم کوریکو اختیار نیکی۔",
        "mycustomjsprotected": "تتے ھیہ جاوا اسکپرٹ (JavaScript) صفحہا ترمیم کوریکو اختیار نیکی۔",
        "myprivateinfoprotected": "تتے ھمی ذاتی معلواتہ (private information) ترمیم کویکو اختیار نیکی۔",
        "mypreferencesprotected": "تتے تان ھمی ترجیحاتہ (preferences) ترمیم کوریکو اختیار نیکی۔",
        "ns-specialprotected": "خاص صفحاتن تدوین کوریکو اجازت نیکی",
        "titleprotected": "ھیہ عنوانو [[User:$1|$1]] تخلیق کوریکاری محفوظ کوری آسور.\nوجہ ھیہ شیر: <em>$2</em>",
+       "filereadonlyerror": "فائل «$1»ہ تبدیلی ممکن نیکی کوریکو کہ خزانہ فائل «$2» فقط خواندگی حالتہ شیر۔\n\nانتظامیو وولٹیاری قلف لیگئیکو حسب ذیل وجہ دیونو بیتی شیر:\n\n«$3»",
+       "invalidtitle": "غلط عنوان",
+       "invalidtitle-knownnamespace": "«$2» نام فضا «$3» متنو سورا مشتمل عنوان نادرست شیر",
+       "invalidtitle-unknownnamespace": "نامعلوم نام فضا عدد «$1» اوچے «$2» متنو سورا مشتمل عنوان نا درست شیر",
+       "exception-nologin": "لاگ ان نو",
+       "exception-nologin-text": "براہ مہربانی! ھیہ صفحا رسائی یا ترمیمو بچے لاگ ان بوس۔",
        "virus-badscanner": "\"خراب وضعیت: نوژان وائرسی مفراس: ''$1''\",",
        "virus-scanfailed": "تفریس ناکام (رمز $1)",
        "virus-unknownscanner": "نوژان ضد وائرس:",
-       "logouttext": "'''ھنیسے تو خارج بیتی آسوس'''<br />\nتو خفی الاسم {{SITENAME}}  استعمال جاری لاکھیکو بوس، یا دوبارہ ھیہ نامو یا مختلف نامان سورا داخل دی بیکو بوس۔  ھیہ یاد آوری کورے کہ ای کما صفحات ھش <span class='plainlinks'>[$1 دوباری لاگن بوس]</span> غیچھی گونی کہ تو ھنیسے خارج نو بیتی آسوس، کلہ پت کہ تو تان تفصحہ (براؤزرو) ابطن (cache) صاف نوکوروس۔\",",
+       "logouttext": "'''ھنیسے تو خارج بیتی آسوس'''<br />\nتو خفی الاسم {{SITENAME}}  استعمال جاری لاکھیکو بوس، یا دوبارہ ھیہ نامو یا مختلف نامان سورا داخل دی بیکو بوس۔  ھیہ یاد آوری کورے کہ ای کما صفحات ھش <span class='plainlinks'>[$1 دوباری لاگن بوس]</span> غیچھی گونی کہ تو ھنیسے خارج نو بیتی آسوس، کلہ پت کہ تو تان تفصحہ (براؤزرو) ابطن (cache) صاف نوکوروس۔\"",
+       "cannotlogoutnow-title": "ھنیسے خارج بیکو نو بوس",
+       "cannotlogoutnow-text": "$1 و استعمالو موژی خارج بیک ممکن نو۔",
+       "welcomeuser": "خوشان گیور، $1!",
+       "welcomecreation-msg": "تہ کھاتہ کھولاو ہوئے۔\nتو [[Special:Preferences|تان ترجیحات]]ہ حسب منشا تبدیلی کوریکو بوس۔",
        "yourname": "اسمِ رکنیت",
        "userlogin-yourname": "اسمِ رکنیت",
        "userlogin-yourname-ph": "تان صارف نام درج کورے",
        "createacct-yourpasswordagain": "کلمۂ اجازتو تصدیق کورے",
        "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": "یا تھے توثیقی ڈیٹابیسا خطا واقع بیتی شیر یا تتے بیریو کھاتو بتاریخ کوریکو اِجازت نیکی",
        "login": "داخل بوس",
+       "login-security": "تان شناختو تصدیقو کورے",
        "nav-login-createaccount": "کھاتہ کھولاو کورے یا اندراج کورے",
        "logout": "لاگ آوٹ",
        "userlogout": "لاگ آوٹ",
        "createacct-reason-ph": "تو ڈبل کھاتہ کھیوتے ساوزیسان؟",
        "createacct-submit": "کھاتہ ساوزاوے",
        "createacct-another-submit": "کھاتہ ساوزاوے",
+       "createacct-continue-submit": "کھاتہ سازی جاری لاکھے",
+       "createacct-another-continue-submit": "کھاتہ سازی جاری لاکھے",
        "createacct-benefit-heading": "{{SITENAME}} تہ غون روئے ایڈٹ کورونیان.",
        "createacct-benefit-body1": "{{PLURAL:$1|ترمیم|ترامیم}}",
        "createacct-benefit-body2": "$1 {{PLURAL:$1|صفحہ|صفحات}}",
        "wrongpassword": "تو غلط کلمۂ شناخت درج کوری آسوس دوبارہ کو شش کورے",
        "wrongpasswordempty": "کلمۂ شناخت ندارد۔ دوبارہ کوشش کورے",
        "passwordtooshort": "تہ منتخب کردہ پارلوظ(پاسورڈ) مختصار شیر. پارلوظ کم از کم {{PLURAL:$1|1 حرف|$1 حروف}} بیلک.",
+       "passwordtoolong": "تہ منتخب کردہ پارلوظ(پاسورڈ) مختصار شیر. پارلوظ کم از کم {{PLURAL:$1|1 حرف|$1 حروف}} بیلک.",
        "password-name-match": "تہ پارلوظ(پاسورڈ) تہ اسمِ صارفو ساری مختلف بیلک.",
        "mailmypassword": "پاسورڈو ری سیٹ کورے",
        "passwordremindertitle": "نوغ عارضی کلمۂ شناخت برائے {{SITENAME}}",
        "emailconfirmlink": "تان برقی پتو تصدیقو کورے",
        "invalidemailaddress": "تہ بشلی کغاز(ای میل) قبول کورونو نو بویان کوریکو کہ ھیہ غلط شکلا شیر.\nبراہِ کرم! ای برقی پتہ(ای میل ایڈرس) صحیح شکلا درج کورے یا ژاغو خالی پیڅھے.",
        "accountcreated": "تخلیقِ کھاتہ",
-       "accountcreatedtext": "تخیلقِ کھاتۂ ممبار براۓ $1۔",
+       "accountcreatedtext": "[[{{ns:User}}:$1|$1]] ([[{{ns:User talk}}:$1|تبادلۂ خیال]]) و صارف کھاتہ ساوز بیتی شیر۔",
        "createaccount-title": "کھاتہ سازی برائے {{SITENAME}}",
        "login-throttled": "تو داخلِ نوشتہ بیکو بچے بو زیادہ کوششیں آرو.\nدوبارہ کوشش کوریکو بچے پھوک مدا انتظار کورے.",
+       "login-abort-generic": "لاگ ان ناکام - منسوخ شد",
        "loginlanguagelabel": "زبان: $1",
        "pt-login": "داخل بوس",
        "pt-login-button": "داخل بوس",
+       "pt-login-continue-button": "داخل بوس",
        "pt-createaccount": "کھاتہ ساوزاوے",
        "pt-userlogout": "لاگ آوٹ",
+       "php-mail-error-unknown": "پی ایچ پیو mail() فنکشنہ نامعلوم نقص۔",
        "changepassword": "پاسورڈو بدیل کورے",
        "resetpass_announce": "تو ای برقی ارسال کردہ عارضی کوڈ ورڈو سوم جستہ داخل بیتی آسوس.\nداخلِ نوشتہ بیکو عملو مکمل کوریکو بچے تہ ھیارا نوغ پاسورڈ متعین کوریلک بوئے جما:",
        "resetpass_header": "کھاتو پاسورڈو تبدیل کورے",
        "newpassword": "نوغ کلمۂ شناخت",
        "retypenew": "نوغ کلمۂ شناخت دوبارہ درج کورے:",
        "resetpass_submit": "پاسورڈ ساوزاوے وا داخل بوس",
+       "botpasswords": "روبہ پاس ورڈ",
+       "botpasswords-disabled": "روبوٹو پاس ورڈ غیر فعال شینی۔",
+       "botpasswords-existing": "روبوٹو موجودہ پاس ورڈ",
+       "botpasswords-createnew": "روبوٹو نوغ پاس ورڈ ساوزاوے",
+       "botpasswords-label-appid": "روبوٹو نام:",
+       "botpasswords-label-create": "ساوزاوے",
+       "botpasswords-label-update": "اپڈیٹ کورے",
+       "botpasswords-label-cancel": "کھینسل",
        "botpasswords-label-delete": "بوغاوے",
        "botpasswords-label-resetpassword": "پاسورڈو ری سیٹ کورے",
+       "botpasswords-label-grants-column": "دیونو ہوئے",
+       "botpasswords-bad-appid": "روبہ نام \"$1\" درست نو۔",
        "resetpass_forbidden": "تتے پاسورڈو چینج کوریکو اجازت نیکی",
        "resetpass-no-info": "ھیہ صفحا براہِ راست رسائیو بچے تہ داخلِ نوشتہ بیک ضروری شیر.",
        "resetpass-submit-loggedin": "پاسورڈو تبدیلی",
        "summary-preview": "نمائش خلاصہ:",
        "subject-preview": "عنوان/شہ سرخیو پیش منظر:",
        "blockedtitle": "صارفو بلاک کورونو بیتی شیر",
+       "blockedtext": "<strong>آپ کے صارف نام یا آئی پی پتہ پر پابندی لگائی جا چکی ہے۔</strong>\n\n$1 نے پابندی عائد کی اور یہ وجہ درج کی: <em>$2</em>\n\n* پابندی کی ابتدا : $8\n* پابندی کا اختتام : $6\n* ممنوع صارف: $7\n\nآپ $1 یا کسی دوسرے [[{{MediaWiki:Grouppage-sysop}}|منتظم]] سے رابطہ کر کے اس پابندی پر گفت و شنید کر سکتے ہیں۔\nواضح رہے کہ آپ «{{int:emailuser}}» کی سہولت اُس وقت تک استعمال نہیں کر سکتے جب تک آپ اپنے [[Special:Preferences|کھاتہ کی ترجیحات]] میں درست برقی ڈاک پتا درج نہ کریں اور آپ کو اِسے استعمال کرنے سے روک نہ دیا گیا ہو۔\nآپ کا موجودہ آئی پی پتہ $3 ہے اور پابندی کا شناختی نمبر #$5 ہے۔\nاگر آپ پابندی سے متعلق کہیں استفسار کریں تو براہِ مہربانی اس میں درج بالا تمام تفصیلات شامل کریں۔",
        "blockednoreason": "کیہ وجہ دیونو نو ھوی",
        "whitelistedittext": "ترمیم کوریکو بچے $1 ضروری شیر.",
        "nosuchsectiontitle": "قطعہ ملاو نو ھوی",
        "accmailtitle": "کلمہ شناخت(پاسورڈ) انځینو ھوی",
        "newarticle": "(نوغ)",
        "newarticletext": "↓تو ای ھݰ صفحو ربطو پیرویو کوری اسوس کہ ھسے ھنیسے موجود نیکی.\nھیہ صفحہو تخلیق کوریکو بچے درج ذیل خانا متنو درج کورے (مزید معلوماتو بچے [$1 صفحۂ معاونت] ملاحظہ کورے).\nاگر تو ھیا غلطیو سورا کہ گیتی اسوس تھے اچھو صفحا آچی بیکو بچے تان کمپیوٹرا '''back''' بٹنو ٹک کورے.",
+       "anontalkpagetext": "----\n<em>یہ تبادلۂ خیال صفحہ ایک ایسے صارف کا ہے جس نے اب تک اپنا کھاتہ نہیں بنایا یا یہ صفحہ اس کے زیر استعمال نہیں۔</em> \nلہٰذا ہمیں اس کی شناخت کے لئے ایک آئی پی پتہ استعمال کرنا پڑ رہا ہے۔ \nاس قسم کا آئی پی پتہ ایک سے زائد صارفین کے درمیان میں مشترک بھی ہوسکتا ہے۔ \nاگر آپ کی موجودہ حیثیت ایک گمنام صارف کی ہے اور آپ محسوس کریں کہ اس صفحہ پر آپ کے متعلق یہ تبصرے غیر متعلق ہیں تو براہ کرم [[Special:CreateAccount|ایک کھاتہ بنا لیں]] یا [[Special:UserLogin|داخل ہو جائیں]] تاکہ مستقبل میں آپ کو گمنام صارفین میں شمار کرنے سے گریز کیا جائے۔",
        "noarticletext": " ھیہ صفحہا فی الحال کیہ متن موجود نیکی.\nتو دیگر صفحاتا [[Special:Search/{{PAGENAME}}|ھیہ صفحہو عنوانو بچے تلاش کوریکو بوس]]، <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} متعلقہ نوشتہ جات تلاش کوریکو بوس],\nیا [{{fullurl:{{FULLPAGENAME}}|action=edit}} تو ھیہ صفحہا ترمیم کوریکو بوس]</span>",
        "noarticletext-nopermission": "ھیہ صفحہا فی الحال کیہ متن موجود نیکی.\nتو دیگر صفحاتا [[Special:Search/{{PAGENAME}}|ھیہ صفحہو عنوانو بچے تلاش کوریکو بوس]]، <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} متعلقہ نوشتہ جات تلاش کوریکو بوس],\nیا [{{fullurl:{{FULLPAGENAME}}|action=edit}} تو ھیہ صفحہا ترمیم کوریکو بوس]</span>",
        "userpage-userdoesnotexist-view": "صارف کھاتہ \"$1\" موجود نیکی۔",
+       "clearyourcache": "<strong>یاددہانی:</strong> محفوظ کرنے کے بعد ان تبدیلیوں کو دیکھنے کے لیے آپ کو اپنے براؤزر کا کیش (cache) صاف کرنا ہوگا۔\n* '''فائرفاکس/ سفاری:''' جب ''Reload'' پر کلک کریں تو ''Shift'' دباکر رکھیں، یا ''Ctrl-F5'' یا ''Ctrl-R'' دبائیں (Mac پر ''R-⌘'')\n* '''گوگل کروم:''' ''Ctrl-Shift-R'' دبائیں (Mac پر ''Shift-R-⌘'')\n* '''انٹرنیٹ ایکسپلورر:''' جب ''Refresh'' پر کلک کریں تو ''Ctrl'' یا ''Ctrl-F5'' دبائیں\n* '''اوپیرا:'''  ''Tools → Preferences'' میں جائیں اور کیش (cache) صاف کریں",
        "updated": "(اپ ڈیٹڈ)",
        "note": "'''نوٹ:'''",
        "previewnote": "'''یاد لاکھے، ھیہ صرفی نمائش شیر، تہ کاردو ترامیم ھنیسے محفوظ کورونو نو بیتی شینی۔'''",
        "post-expand-template-inclusion-category": "ھش صفحات کہ ھتیرا ٹمپلیٹ یعنی سانچو ناپ لوٹ بیتی شیر۔",
        "post-expand-template-argument-warning": "'''خبردار:''' ھیہ صفحا ای سانچہ(ٹمپلیٹ) مشقولگی دیونو بیتی شیر وا ھمو سایز بولوٹ شیر۔\nھمی لوان نیزونو بیتی شیر",
        "post-expand-template-argument-category": "ھش صفحات کہ ھتیرا بوغینو بیرو سانچان یعنی(ٹمپلیٹان) لو شینی۔",
+       "undo-failure": "درمیان میں متنازع ترامیم کی موجودگی کی بنا پر اس ترمیم کو واپس نہیں پھیرا جا سکا۔",
        "viewpagelogs": "ھیہ صفحہو بچے نوشتہ جاتن لوڑے",
        "currentrev-asof": "حالیہ نظرثانی بمطابق $1",
        "revisionasof": "تجدید بمطابق $1",
        "revdel-restore": "ظاہریتو تبدیل کورے",
        "mergehistory-reason": "وجہ:",
        "mergehistory-revisionrow": "$1 ($2) $3 . . $4 $5 $6",
+       "mergelog": "نوشتو انضمام",
        "revertmerge": "غیر ضم",
        "history-title": "تاریخچہ \"$1\"",
        "difference-title": "ایڈٹ کاردوان موژی فرق \"$1\"",
        "editundo": "آچی(Undo)",
        "diff-empty": "(کیہ فرق نیکی)",
        "diff-multi-sameuser": "({{PLURAL:$1|One intermediate revision|$1 intermediate revisions}} by the same user not shown)",
+       "diff-multi-otherusers": "({{PLURAL:$2|ایک دوسرے صارف|$2 صارفین}} {{PLURAL:$1|کا ایک درمیانی نسخہ نہیں دکھایا گیا|$1 کے درمیانی نسخے نہیں دکھائے گئے}})",
        "searchresults": "تلاشو نتیجہ",
        "searchresults-title": "نتائجِ تلاش برائے \"$1\"",
        "notextmatches": "ھیہ عنوانو سورا کیہ دی صفحہ موجود نیکی",
        "filehist-comment": "تبصرہ",
        "imagelinks": "مسلو روابط",
        "linkstoimage": "ھیہ مسلو سوم درج ذیل {{PLURAL:$1|صفحہ مربوط شیر|$1 صفحات مربوط شینی}}",
+       "linkstoimage-more": ".",
        "nolinkstoimage": "ھیہ کھوار ویکیپیڈیا ھش کیہ صفحات نیکی کہ ھتیت ھیہ مسل (فائلو) متعلقہ شینی",
        "linkstoimage-redirect": "$1 (فائل ری ڈائرکٹ) $2",
        "sharedupload-desc-here": "ھیہ فائل $1 موژاری شیر وا ھیہ خور پرجیکٹہ استعمال بویان۔\nمزید معلومات ھمو [$2 فائل مشقولگی صفحہا]  دیونو بیتی شیر",
        "speciallogtitlelabel": "ہدف (عنوان یا {{ns:user}}:صارفو نام برائے صارف):",
        "log": "نوشتہ جات",
        "all-logs-page": "تمام عوامی نوشتہ جات",
+       "alllogstext": "{{SITENAME}} کے تمام دستیاب لاگز کا پیوستہ ڈسپلے۔\nآپ اور باریکی کے لیے لاگ کی قسم، صارف نام (حساس معاملہ)، یا متاثرہ صفحہ (یہ بھی حساس معاملہ) چن سکتے ہیں۔",
+       "logempty": "نوشتہ میں اس سے مشابہ کوئی اندراج موجود نہیں ہے۔",
        "allpages": "سف صفحات",
        "prevpage": "آچھو صفحہ ($1)",
        "allpagesfrom": "مطلوبہ حرفاری شروع باک صفحاتن نمائش:",
        "watchthispage": "ھیہ صفحو تان نظرا لاکھے",
        "unwatch": "زیرنظرمنسوخ",
        "watchlist-details": "تہ زیرِنظرفہرستا {{PLURAL:$1|$1 صفحہ شیر|$1 صفحات شینی}}، ھیارا تبادلۂ خیالو صفحاتن تعداد شامل نیکی.",
+       "wlheader-showupdated": "آپ کی آخری آمد کے بعد جن صفحات میں تبدیلی ہوئی ہے وہ <strong>جلی حروف</strong> میں نظر آئیں گے۔",
+       "wlnote": "ذیل میں گزشتہ {{PLURAL:$2|گھنٹے|<strong>$2</strong> گھنٹوں}} میں ہونے والی {{PLURAL:$1|تبدیلی|<strong>$1</strong> تبدیلیوں}} کی فہرست درج ہے، تاریخ تجدید $3، $4",
        "watchlist-options": "واچ لسٹ آپشن",
        "watching": "زیر نظر",
        "unwatching": "منسوخ",
        "mycontris": "مہ حصہ",
        "anoncontribs": "آرٹیکلز",
        "contribsub2": "{{GENDER:$3|$1}} ($2)",
+       "nocontribs": "اس معیار کے مطابق کوئی ترمیم دستیاب نہیں ہوئی۔",
        "uctop": "موجودہ نسخہ",
        "month": "مس (وا ھیغاری پروشٹی):",
        "year": "سال (وا ھیغاری پروشٹی):",
        "contribslink": "حصہ داری",
        "blocklogpage": "نوشتۂ پاوبندی",
        "blocklogentry": "بلاک[[$1]] وختہ پت $2 $3",
+       "reblock-logentry": "[[$1]] کی ترتیبات پابندی کو تبدیل کیا، اب میعاد $2 $3 پر ختم ہوگی",
        "unblocklogentry": "بلاک نو کاردو $1",
        "block-log-flags-nocreate": "کھاتہ کھولاو کوریکو سورا پاوپندی شیر",
        "ipb_expiry_invalid": "Expiry ٹیم غلط شیر.",
        "pageinfo-few-watchers": "$1 سے کم {{PLURAL:$1|ناظر|ناظرین}}",
        "pageinfo-redirects-name": "ری ڈائرکٹان تعداد",
        "pageinfo-subpages-name": "ھیہ صفحو ذیلی صفحاتن تعداد",
+       "pageinfo-subpages-value": "$1 ($2 {{PLURAL:$2|رجوع مکرر|رجوع مکررات}}؛ $3 {{PLURAL:$3|غیر رجوع مکرر|غیر رجوع مکررات}})",
        "pageinfo-firstuser": "صفحہ ساوزیاک",
        "pageinfo-firsttime": "صفحہ ساوزیکو تاریخ",
        "pageinfo-lastuser": "آخری ترمیم کوراک",
        "pageinfo-recent-authors": "مختلف مصنفینان حالیہ تعداد",
        "pageinfo-magic-words": "جادوئی {{PLURAL:$1|لوظ|الفاظ}} ($1)",
        "pageinfo-hidden-categories": "کھوشت {{PLURAL:$1|زمرہ|زمرہ جات}} ($1)",
+       "pageinfo-templates": "زیر استعمال {{PLURAL:$1|سانچہ|سانچے}} ($1)",
        "pageinfo-toolboxlink": "معلومات صفحہ",
+       "pageinfo-contentpage": "شمار بطور صفحہ",
        "pageinfo-contentpage-yes": "دی",
        "patrol-log-page": "پیٹرول لاگ",
        "previousdiff": " ← پرانو تدوین",
        "nextdiff": "صفحہو نم:",
        "widthheightpage": "$1×$2، $3 {{PLURAL:$3|صفحہ|صفحات}}",
        "file-info-size": "$1 × $2 پکسلز, فل سائز: $3, MIME ٹائپ: $4",
+       "file-info-size-pages": "$1 × $2 پکسل، فائل کا حجم: $3، MIME قسم: $4، $5 {{PLURAL:$5|صفحہ|صفحات}}",
        "file-nohires": "ھموغاری لوٹ ریزولیوشن موجود نیکی.",
        "svg-long-desc": "SVG فایل, nominally $1 × $2 پکسلز, فایل سایز: $3",
        "show-big-image": "اصل فائل",
        "watchlisttools-raw": "نوغ واچ لسٹان ایڈیٹ کورے",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|talk]])",
        "duplicate-defaultsort": "'''خبردار:''' ڈیفالٹ تاڑٰ(نغڑی) \"$2\" پروشٹیو ڈیفالٹ تاڑا \"$1\" لیگی شیر۔",
+       "redirect": "فائل، صارف، صفحہ، نسخہ، یا نوشتہو شناختاری رجوع مکرر",
+       "redirect-summary": "ھیہ خصوصی صفحہو ذریعا فائل (درج کاردو فائلو نام)، صفحہ (صفحہ یا نسخو درج کاردو شناختی نمبر)، صفحہ صارف (صارفو درج کاردو شناختی نمبر) یا اندراج نوشتہ (نوشتو درج کاردو شناختی نمبر)و رجوع مکرر حاصل کورونو بوئے۔ طریقہ استعمال: [[{{#Special:Redirect}}/file/Example.jpg]]، \n[[{{#Special:Redirect}}/page/64308]]، [[{{#Special:Redirect}}/revision/328429]] یا [[{{#Special:Redirect}}/user/101]] یا \n[[{{#Special:Redirect}}/logid/186]]۔",
        "redirect-submit": "بوغے لا",
        "redirect-lookup": "تلاش:",
        "redirect-value": "قدر:",
        "compare-page1": "صفحہ 1",
        "logentry-delete-delete": "$1 {{GENDER:$2|حذف کورونو ہوئے}} صفحہ $3",
        "logentry-delete-restore": "$1 صفحو $3 {{GENDER:$2|بحال آریر}}",
+       "logentry-delete-revision": "$1 نے $3 میں موجود {{PLURAL:$5|ایک نسخے|$5 نسخوں}} کی مرئیت کو {{GENDER:$2|تبدیل کیا}}: $4",
        "revdelete-content-hid": "موادو کھوشتئینو بیتی شیر",
        "logentry-move-move": "$1 {{GENDER:$2|moved}} صفحہ $3  پت $4",
        "logentry-move-move-noredirect": "$1 صفحہ $3 و $4 وولٹی ری ڈائرکٹ {{GENDER:$2|آریر}}",
        "logentry-move-move_redir": "$1 ری ڈائرکٹان ہٹاو کوری صفحہ $3 و $4 وولٹی {{GENDER:$2|منتقل آریر}}",
+       "logentry-patrol-patrol-auto": "$1 صفحہ $3 و نسخو $4 خودکار طورا مراجعت شدہ {{GENDER:$2|نشان زد آریر}}",
        "logentry-newusers-create": "صارف کھاتہ $1 {{GENDER:$2|ساوزیینو ھوئے}}",
        "logentry-newusers-autocreate": "صارف کھاتہ $1 خودکار طورا {{GENDER:$2|ساوز ہوئے}}",
        "logentry-upload-upload": "$1 {{GENDER:$2|uploaded}} $3",
index 7b8b114..769891d 100644 (file)
        "undo-norev": "문서가 없거나 삭제되었기 때문에 편집을 되돌릴 수 없습니다.",
        "undo-nochange": "편집이 이미 되돌려진 것으로 나타납니다.",
        "undo-summary": "[[Special:Contributions/$2|$2]] ([[User talk:$2|토론]])의 $1판 편집을 되돌림",
+       "undo-summary-anon": "[[Special:Contributions/$2|$2]]의 $1 판을 되돌림",
        "undo-summary-username-hidden": "숨겨진 사용자가 $1 판을 되돌림",
        "cantcreateaccount-text": "현재 IP 주소('''$1''')는 [[User:$3|$3]] 사용자에 의해 계정 만들기가 차단되었습니다.\n\n차단 이유는 다음과 같습니다: $2",
        "cantcreateaccount-range-text": "당신의 IP 주소(<strong>$4</strong>)가 속해 있는 <strong>$1</strong> 대역에서의 계정 만들기를 [[User:$3|$3]]님이 차단했습니다.\n\n$3님이 제시한 이유는 \"$2\"입니다.",
        "search-interwiki-more": "(더 보기)",
        "search-interwiki-more-results": "더 많은 결과",
        "search-relatedarticle": "관련",
+       "search-invalid-sort-order": "$1의 정렬 순서를 인식하지 못했습니다. 기본 정렬이 적용됩니다. 유효한 정렬 순서는 다음과 같습니다: $2",
+       "search-unknown-profile": "$1의 검색 프로파일을 인식하지 못했습니다. 기본 검색 프로파일이 적용됩니다.",
        "searchrelated": "관련",
        "searchall": "모두",
        "showingresults": "'''$2'''번 부터의 {{PLURAL:$1|결과 '''1'''개|결과 '''$1'''개}}입니다.",
        "move": "이동",
        "movethispage": "이 문서 이동하기",
        "unusedimagestext": "다음은 어떠한 문서에서도 사용하지 않는 파일의 목록입니다.\n다른 사이트에서 URL 접근을 통해 파일을 사용할 수 있기 때문에, 아래 목록에 있는 파일도 실제로 사용 중일 가능성이 있다는 점을 주의해주세요.",
+       "unusedimagestext-categorizedimgisused": "다음의 파일이 존재하지만 어느 문서에도 포함되어 있지 않습니다. 분류된 이미지는 문서에 포함되어 있지 않음에도 사용되는 것으로 간주됩니다.\n다른 웹사이트가 파일을 직접 URL에 링크할 수 있으므로 실제 사용되지 않는 경우 여기에 나열될 수 있음을 참고해 주십시오.",
        "unusedcategoriestext": "사용하지 않는 분류 문서의 목록입니다.",
        "notargettitle": "해당하는 문서 없음",
        "notargettext": "기능을 수행할 대상 문서나 사용자를 지정하지 않았습니다.",
        "alreadyrolled": "[[:$1]]에서 [[User:$2|$2]] ([[User talk:$2|토론]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]])의 편집을 되돌릴 수 없습니다.\n누군가가 이미 문서를 고치거나 되돌렸습니다.\n\n마지막으로 이 문서를 편집한 사용자는 [[User:$3|$3]] ([[User talk:$3|토론]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]])입니다.",
        "editcomment": "편집 요약: <em>$1</em>",
        "revertpage": "[[Special:Contributions/$2|$2]]([[User talk:$2|토론]])의 편집을 [[User:$1|$1]]의 마지막 판으로 되돌림",
+       "revertpage-anon": "[[Special:Contributions/$2|$2]]의 편집을 [[User:$1|$1]]의 마지막 판으로 되돌림",
        "revertpage-nouser": "숨긴 사용자의 편집을 {{GENDER:$1|[[User:$1|$1]]}}의 마지막 판으로 되돌림",
        "rollback-success": "{{GENDER:$3|$1}}의 편집을 되돌렸습니다.\n{{GENDER:$4|$2}}의 마지막 판으로 바뀌었습니다.",
        "sessionfailure-title": "세션 실패",
        "contribsub2": "{{GENDER:$3|$1}}($2)의 기여",
        "contributions-subtitle": "{{GENDER:$3|$1}}의 기여",
        "contributions-userdoesnotexist": "\"$1\" 사용자 계정은 등록되어 있지 않습니다.",
+       "negative-namespace-not-supported": "음수값의 이름공간은 지원되지 않습니다.",
        "nocontribs": "지정한 조건과 일치하는 바뀜을 찾을 수 없습니다.",
        "uctop": "최신",
        "month": "월:",
        "permanentlink-revid": "판 ID",
        "permanentlink-submit": "판으로 이동",
        "newsection": "새 문단",
+       "newsection-page": "대상 문서",
        "newsection-submit": "문서로 이동",
        "dberr-problems": "죄송합니다! 이 사이트에 기술적인 문제가 발생하고 있습니다.",
        "dberr-again": "잠시 기다리고 나서 다시 불러오세요.",
        "specialmute-success": "알림 미표시 환경 설정이 업데이트되었습니다. [[Special:Preferences|환경 설정]]에서 알림이 표시되지 않는 모든 사용자를 확인하십시오.",
        "specialmute-submit": "확인",
        "specialmute-label-mute-email": "이 사용자의 이메일 알림을 표시하지 않습니다",
-       "specialmute-header": "<b>{{BIDI:[[User:$1]]}}</b>의 알림 미표시 환경 설정을 선택해 주십시오.",
+       "specialmute-header": "사용자 <b>{{BIDI:[[User:$1]]}}</b>의 알림 미표시 환경 설정을 선택해 주십시오.",
        "specialmute-error-invalid-user": "요청한 사용자 이름을 찾을 수 없습니다.",
-       "specialmute-email-footer": "{{BIDI:$2}}의 이메일 환경 설정을 관리하려면 <$1>을(를) 방문해 주십시오.",
+       "specialmute-error-no-options": "알림 미표시 기능을 사용할 수 없습니다. 다음의 이유일 수 있습니다: 이메일 주소를 인증하지 않았거나 위키 관리자가 이 위키에 이메일 기능 및 이메일 블랙리스트를 비활성화했습니다.",
+       "specialmute-email-footer": "사용자 {{BIDI:$2}}의 이메일 환경 설정을 관리하려면 <$1>을(를) 방문해 주십시오.",
        "specialmute-login-required": "알림 미표시 환경 설정을 변경하려면 로그인해 주십시오.",
        "mute-preferences": "알림 미표시 환경 설정",
        "revid": "$1 판",
        "passwordpolicies-policy-passwordnotinlargeblacklist": "비밀번호는 가장 흔히 쓰이는 비밀번호 100,000개 목록에 속할 수 없습니다.",
        "passwordpolicies-policyflag-forcechange": "로그인 시 변경 필요",
        "passwordpolicies-policyflag-suggestchangeonlogin": "로그인할 때 변경 제안",
+       "mycustomjsredirectprotected": "넘겨주기이면서 사용자 공간 안에 참조하고 있지 않으므로 이 자바스크립트 페이지를 편집할 권한이 없습니다.",
        "easydeflate-invaliddeflate": "주어진 컨텐츠가 적절히 압축되지 않았습니다",
        "unprotected-js": "보안 상의 이유로 자바스크립트는 보호되지 않은 문서로부터 불러올 수 없습니다. 미디어위키: 이름공간이나 사용자의 하위 문서에서만 자바스크립트를 만들어 주십시오.",
        "userlogout-continue": "로그아웃하시겠습니까?"
index 54cc55c..70f259b 100644 (file)
        "editfont-monospace": "فونت هم عرض",
        "editfont-sansserif": "فونت بدون سریف",
        "editfont-serif": "فونت سریف",
-       "sunday": "یە شأمە",
-       "monday": "دوٙشمە",
-       "tuesday": "سەشمە",
-       "wednesday": "چار شأمأھ",
-       "thursday": "پأشأمە",
+       "sunday": "یه شمبد",
+       "monday": "دوشمبد",
+       "tuesday": "سەشمبد",
+       "wednesday": "چار شمبد",
+       "thursday": "پنشمبد",
        "friday": "جمه",
        "saturday": "شمبە",
        "sun": "یە شمبد",
        "mon": "دوشمبد",
-       "tue": "سەشمبد",
+       "tue": "سە شمبد",
        "wed": "چارشمبد",
        "thu": "پیشمبد",
        "fri": "جمَه",
-       "sat": "شأمأھ",
-       "january": "أڤأل قأھارھ",
-       "february": "Ù\84Û\8cرÛ\8cØ´Ú¯Ù\88Ù\99Ù\86",
-       "march": "ئنهزینوٙن",
-       "april": "نۉروٙزماھ",
-       "may_long": "گۉلبارماھ",
-       "june": "جۉریش",
-       "july": "میڤە رأسوٙن",
-       "august": "مە گأرمە",
-       "september": "Ø´Û\8cÙ\86Û\8cارÙ\88Ù\99Ù\86",
-       "october": "مالبارکوٙنوٙن",
-       "november": "ئا سأردکوٙنوٙن",
-       "december": "ئا Ø±Û\8cجÛ\8cÚ©Ù\86Ù\88Ù\99Ù\86",
+       "sat": "شمبد",
+       "january": "ژانویه",
+       "february": "Ù\81Ù\88رÛ\8cÙ\87",
+       "march": "مارس",
+       "april": "آوریل",
+       "may_long": "مه",
+       "june": "ژوئن",
+       "july": "ژوئیه",
+       "august": "اوت",
+       "september": "سپتاÙ\85بر",
+       "october": "اکتبر",
+       "november": "نوامبر",
+       "december": "دساÙ\85بر",
        "january-gen": "أڤأل قأهارھ",
        "february-gen": "لیریشگوٙن",
        "march-gen": "ئنهزینوٙن",
        "october-gen": "مالبارکوٙنوٙن",
        "november-gen": "ئا سأردکوٙنوٙن",
        "december-gen": "ئا ریجیکنوٙن",
-       "jan": "أڤأل قأھارھ",
-       "feb": "Ù\84Û\8cرÛ\8cØ´Ú¯Ù\88Ù\99Ù\86",
-       "mar": "ئنهزینوٙن",
-       "apr": "نۉروٙزماھ",
-       "may": "گوٙلبار ماھ",
-       "jun": "جوٙریش",
-       "jul": "میڤە رأسوٙن",
-       "aug": "مە گأرمە",
-       "sep": "Ø´Û\8cÙ\86Û\8cارÙ\88Ù\99Ù\86",
-       "oct": "مالبارکوٙنوٙن",
-       "nov": "ئا سأردکوٙنوٙن",
+       "jan": "ژانویه",
+       "feb": "Ù\81Ù\88رÛ\8cÙ\87",
+       "mar": "مارس",
+       "apr": "آوریل",
+       "may": "مه",
+       "jun": "ژوئن",
+       "jul": "ژوئیه",
+       "aug": "اوت",
+       "sep": "سپتاÙ\85بر",
+       "oct": "اکتبر",
+       "nov": "نوامبر",
        "dec": "دسامبر",
        "january-date": "ژانویه $1",
        "february-date": "فوریه $1",
        "mypage": "بلگه",
        "mytalk": "گأپ",
        "anontalk": "سی ای آدرس آی پی گپ بزه",
-       "navigation": "هدایت کیردأن",
+       "navigation": "هدایت کردن",
        "and": "&#32;ڤ",
        "faq": "اف آی کیو \" سوالل متداول \"",
        "actions": "عملیه یل",
        "namespaces": "هۉمدیرأنگل",
        "variants": "أنۉاع",
-       "navigation-heading": "مأنۉ ناۉ ۉری",
+       "navigation-heading": "منوی ناوبری",
        "errorpagetitle": "خطا",
        "returnto": "بازگشت ڤە $1.",
        "tagline": "زھ {{SITENAME}}",
-       "help": "Ù\87Ù\88Ù\99میاری",
-       "search": "جۉستأن",
-       "searchbutton": "جۉستأن",
+       "help": "Ù\87Ù\8fمیاری",
+       "search": "جُستن",
+       "searchbutton": "جُستن",
        "go": "رو",
-       "searcharticle": "رÛ\89",
+       "searcharticle": "برÙ\8eÙ\87",
        "history": "ڤیرگار ھ بألگە",
        "history_short": "ڤیرگار",
        "updatedmarker": "بهروز وابی تا موقع آخرین سیل کردن مو",
        "print": "چاپ",
        "view": "نما",
        "view-foreign": "نیما مئن  $1",
-       "edit": "ئÛ\8cصلاح",
+       "edit": "اصلاح",
        "edit-local": "اصلاح توضیحتل محلی",
        "create": "درست کردن",
        "create-local": "ڤأندن توٙضیحأتل مأحألی",
        "talkpagelinktext": "گپ",
        "specialpage": "بلگه مخصوص",
        "personaltools": "ئوزارگل سی خۉتی",
-       "talk": "قسە",
+       "talk": "گپ",
        "views": "نمایل",
-       "toolbox": "ئÙ\88زارگÛ\95",
+       "toolbox": "ابزارئÙ\84",
        "imagepage": "دیئن بلگه فایل",
        "mediawikipage": "دیئن بلگه پیوم",
        "templatepage": "دیئن بلگه قالب",
        "protectedpage": "بلگه حفاظت وابیه",
        "jumpto": "پریدن ڤھ:",
        "jumptonavigation": "هدایت کردن",
-       "jumptosearch": "جۉستأن",
+       "jumptosearch": "جُستن",
        "view-pool-error": "وبشید ، سرور بیش زه حد بارگیری وابیه .\nکارورل زیادی ایخن ای بلگنه سل کنن.\nلطفا یه لحظه واسیت قبلیکه به خیت ای بلگنه مجددا سل کیت.\n$1",
        "generic-pool-error": "وبشید ، سرور بیش زه حد بارگیری وابیه .\nکارورل زیادی ایخن ای منوبنه سل کنن.\nلطفا یه لحظه واسیت قبلیکه به خیت ای منوبنه مجددا سل کیت.",
        "pool-timeout": "پایان زمون اتنظار سی قفل",
        "currentevents": "اتفاقل جاری",
        "currentevents-url": "Project:اتفاقل جاری",
        "disclaimers": "ئینکار کنندھ یل",
-       "disclaimerpage": "Project:ئÛ\8cÙ\86کار Ú©Ø§Ø±Û\89أراÙ\86",
+       "disclaimerpage": "Project:تکذÛ\8cبâ\80\8c Ù\86Ù\88Ù\85Ù\90Û\8c Ø¹Ù\85Ù\88Ù\85Û\8c",
        "edithelp": "هوٙمیاری سی ئیصلاح",
        "mainpage": "ولاگ اصلی",
        "mainpage-description": "بألگە أصلی",
        "policy-url": "Project:خط مشی",
-       "portal": "دأرگاھ کارڤأرل",
-       "portal-url": "Project:دأرگاھ کارڤأرل",
+       "portal": "ورودی کاربرئل",
+       "portal-url": "Project:ورودی کاربرئل",
        "privacy": "خط مأشی رازداری",
-       "privacypage": "Project:خط Ù\85أشÛ\8c Ø±Ø§Ø²Ø¯Ø§Ø±Û\8c",
+       "privacypage": "Project:سÛ\8cاست Ù\85حرÙ\85اÙ\86Ù\87",
        "badaccess": "خطا دسترسی",
        "badaccess-group0": "ایسا اجازه انجام کاری که ایخستیده ندارین",
        "badaccess-groups": "او کاری که ایسا درخواست کردین فقط سی کارورانیه که مئنه ای  گروهن  {{PLURAL:$2|آن گروه|یکی زه گروه یل}}: $1.",
        "versionrequired": "یه نسخه زه نیازمندی یل ویکی مدیا\n$1",
        "versionrequiredtext": "یه نسخه زه ویکی مدیا($1) نیازمند ه وه استفاده زه ای بلگه\nبویین :[[مخصوص:نسخه|نسخه مخصوص]].",
        "ok": "خووه",
-       "retrievedfrom": "بازÛ\8cاÙ\81ت Ø²Ú¾ \"$1\"",
+       "retrievedfrom": "برگرÙ\81تÙ\87 Ù\88Ù\87 Â«$1»",
        "youhavenewmessages": "پیوم نو داری $1 ($2).",
        "youhavenewmessagesfromusers": "{{PLURAL:$4|ایشا داریت}} $1 زه {{PLURAL:$3|یه کارور دیه|$3 کارورل}} ($2).",
        "youhavenewmessagesmanyusers": "ایشا $1 زه کارورل دیه داریت ($2).",
        "createaccount-title": "اکانت سازی سی {{SITENAME}}",
        "login-abort-generic": "ورود ایشا ناموفق وابی - سقط وابی",
        "loginlanguagelabel": "زوٙوٙن:$1",
-       "pt-login": "ئÛ\89Û\8cدأÙ\86 Ú¤Ú¾ Ø³Û\8cستÙ\85",
+       "pt-login": "داخÙ\8fÙ\84 Ù\88ابÛ\8cدÙ\86",
        "pt-login-button": "ئۉیدن ۉھ سیستم",
-       "pt-createaccount": "راس Ú©Û\8cردأÙ\86 Ø­Û\8cسآÛ\89",
+       "pt-createaccount": "دÙ\8fرÙ\8fس Ú©Ù\90ردÙ\8eÙ\86 Ø­Ø³Ø§Ø¨",
        "pt-userlogout": "رأتن زھ سیستم",
        "changepassword": "تغییر رمز",
        "resetpass_announce": "سی پایان ورود ، ایشا واسی یه رمز جدید سیخوت به ونی.",
        "rev-delundel": "قابلیأت تأغییر دائن",
        "history-title": "تاریخچه اصلاحل $1",
        "difference-title": "فرخ ۉا بین تجدید نطرل \"$1\"",
-       "lineno": "سأطر $1:",
+       "lineno": "سطر $1:",
        "editundo": "لأغڤ",
        "diff-multi-sameuser": "({{PLURAL:$1|یه ۉرزن متۉسط|$1 ۉرژنل متۉسط}} تۉسط کارۉر مشابه نشۉ نۉابیه)",
        "searchresults": "نأتیجل جۉستأن",
        "right-writeapi": "ئیستفادھ د نڤشتن ڤە صوٙرأت API",
        "newuserlogpage": "سیاهە راس کیردأن حیسآۉ",
        "enhancedrc-history": "ڤیرگار",
-       "recentchanges": "تأغÛ\8cÛ\8cرÙ\84 Ù\86Û\89",
+       "recentchanges": "تغÛ\8cÛ\8cرئÙ\84 Ù\86Ù\88",
        "recentchanges-legend": "گۉزینە یل تأغییرل أخیر",
        "recentchanges-summary": "شیار تأغییرل أخیر مئنە ئی بألگە ڤە ڤیکی .",
        "recentchanges-label-newpage": "ئی ئیصلاح یە بألگە نوٙ ئیسازھ",
        "nolinkstoimage": "ای پرونده مِن هیچ صفحه‌ای و کار نرته.",
        "sharedupload-desc-here": "ئی فایل ز $1 ئوٙمائە ڤ شاید د پۉرۉجە یل دیە مورد ئیستفادھ ڤابین.\nتوٙضیحتل ری [$2 بألگە تۉضیح فایل] دوٙمین نیشۉ ڤابیە .",
        "upload-disallowed-here": "ئیشا نیتأریت ئی فایلنە بینڤیسیت",
-       "randompage": "بألگە بأختە کی",
+       "randompage": "ولاگ شانسی",
        "nbytes": "$1 {{PLURAL:$1|بایت|بایتل}}",
        "nmembers": "$1 {{PLURAL:$1|عضۉ|اعضۉل}}",
        "newpages": "بألگە یل نوٙ",
        "month": "مئنھ ای ماھ (ۉ قبل زھ ھۉ):",
        "year": "مئنھ ای سال (ۉ قبل زھ ھۉ):",
        "sp-contributions-submit": "جُستن",
-       "whatlinkshere": "لینکل ئی بألگە",
+       "whatlinkshere": "لینکئل ای ولاگ",
        "whatlinkshere-title": "بألگل کە لینک دائنە ڤە \"$1\"",
        "whatlinkshere-page": "بألگە:",
        "linkshere": "لینک ھ بألگل دوٙمین الذیکر ڤە '''$2''':",
        "tooltip-pt-preferences": "ترجیحئل {{GENDER:|ایشا}}",
        "tooltip-pt-watchlist": "لیست بألگلی کە ئیشا تأغییرل هۉنۉنە  دۉنبال ئیکۉنین",
        "tooltip-pt-mycontris": "لیست سأھمیل ئیشا",
-       "tooltip-pt-login": "توٙصیە ڤابوٙھ کە ڤە سیستم داخل بوٙین. أما ئیجباری نیسس",
+       "tooltip-pt-login": "توصیه ایکنیم که وه سیستم وارد وابید، گرچه اجباری نیسی",
        "tooltip-pt-logout": "رأتن زھ سیستم",
        "tooltip-pt-createaccount": "توٙصیە ڤابوٙھ کە حسآڤ کارڤأری راس بکنیت یا ڤە سیستم داخل بوٙین. اما ئیجباری نیسس",
-       "tooltip-ca-talk": "قسە د بألگە مۉحتڤا",
+       "tooltip-ca-talk": "گپئل دربارهٔ محتوِی ولاگ",
        "tooltip-ca-edit": "ایسھ ترین ای بلگھ نھ اصلاح کنیت.لطفا قبل اصلاح ای بلگھ ز دۉکمه پیش نمایش استفاده کنیت",
        "tooltip-ca-addsection": "ئاغاز کیردأن یە قسمت نوٙ",
        "tooltip-ca-viewsource": "ئی بألگە دوٙمین حیمایأتە. \nئیشا تأرین سأرچیشمە سە بیخوٙنیت",
        "tooltip-ca-history": "ڤیرگار",
        "tooltip-ca-move": "جابجاکردن ای بلگه",
        "tooltip-ca-watch": "ئیضاف کردن ئی بألگە ڤە لیست پیگیری یل ئیشا",
-       "tooltip-search": "جۉستأن {{SITENAME}}",
-       "tooltip-search-go": "رÛ\89 Ù\85أئÙ\86Ù\87 Ø¨Ø£Ù\84Ú¯Û\95 Ø¦Û\8c Ú¤Ø§ Ø¦Û\8c Ù\86Û\89Ù\85 Ø£Ø± Ù\87Û\8cسس",
-       "tooltip-search-fulltext": "جۉستأن بألگە یل سی ئی مأتن",
+       "tooltip-search": "جُستن {{SITENAME}}",
+       "tooltip-search-go": "أر Ø§Û\8cترÛ\8cد Ù\88Ù\87 Ù\88Ù\84اگÛ\8c Ø¨Û\8c Ù\87Ù\85Û\8c Ù\86Ù\88Ù\88Ù\85 Ø¨Ø±Û\8cد.",
+       "tooltip-search-fulltext": "جُستن ای جمله مِن ولاگئل",
        "tooltip-p-logo": "رۉ د بألگە أصلی",
        "tooltip-n-mainpage": "رۉ د بألگە أصلی",
        "tooltip-n-mainpage-description": "رۉ د بألگە أصلی",
        "tooltip-n-recentchanges": "سیائل تأغییرل آخر مئن ئی ڤیکی",
        "tooltip-n-randompage": "سڤار کردن یە بألگە بأختە کی",
        "tooltip-n-help": "ینە جا سی سیل کردن",
-       "tooltip-t-whatlinkshere": "فهرست همە بألگە یل ڤیکی کە ئیچوٙ لینک دارن",
+       "tooltip-t-whatlinkshere": "فهرست همِی صفحئلی که وه ای صفحه پیوند ایخرن",
        "tooltip-t-recentchangeslinked": "تأغییرل آخر مئن بألگە کە لینک دانە ڤە ئی بألگە",
        "tooltip-feed-atom": "تأغذیە کچک تأرین جۉزء  ئی بألگە",
        "tooltip-t-contributions": "لیست مشارکتئل توسط {{GENDER:$1|این کاربر}}",
        "tooltip-t-upload": "بلم گیر کردن فایلل",
-       "tooltip-t-specialpages": "بألگە یل ڤیجە",
-       "tooltip-t-print": "Ù\88Û\8cرÚ\98Ù\86 Ø³Û\8c Ú\86اپ Ø¦Û\8c Ø¨Ø£Ù\84Ú¯Û\95",
+       "tooltip-t-specialpages": "فهرستی وه همی ولاگئل ویژه",
+       "tooltip-t-print": "Ù\86سخÙ\90Û\8c Ù\82ابÙ\84 Ú\86اپ Ø§Û\8c ØµÙ\81Ø­Ù\87",
        "tooltip-t-permalink": "لینکل دائمی ڤە ئی ۉیرژن ئی بألگە",
        "tooltip-ca-nstab-main": "دیئن بألگە مۉحتڤا",
        "tooltip-ca-nstab-user": "دیئن بألگە کارڤأر",
        "monthsall": "همه",
        "semicolon-separator": "؛&#32;",
        "signature": "[[{{ns:user}}:$1|$2]] ([[{{ns:user_talk}}:$1|گأپ]])",
-       "specialpages": "بألگە یل ڤیجە",
+       "specialpages": "ولاگئل ویژه",
        "tag-filter": "[[Special:Tags|بأرچأسب]] فیلتر:",
        "tag-list-wrapper": "[[Special:Tags|{{PLURAL:$1|بأرچسب|بأرچسبل}}]]: $2",
        "logentry-delete-delete": "$1 {{GENDER:$2|حأذف ڤابیدھ}} بألگە $3",
        "logentry-move-move": "$1 {{GENDER:$2|انتقال دادھ بیه}} بلگه $3 ۉھ $4",
        "logentry-newusers-create": "حسآۉ کارڤأر $1 ڤابیە {{GENDER:$2|راس ڤیدھ }}",
        "logentry-upload-upload": "$1 {{GENDER:$2|بلم گیر کردھ ۉابی}} $3",
-       "searchsuggest-search": "جÙ\8fستÙ\8eÙ\86Ù\92",
+       "searchsuggest-search": "جÙ\8fستÙ\86",
        "specialmute": "بی‌صدا",
        "userlogout-continue": "ایخیت برِیِتو وَدَر"
 }
index b50b012..ed6500b 100644 (file)
        "history": "hronoloģija",
        "history_short": "Vēsture",
        "history_small": "vēsture",
-       "updatedmarker": "atjaunināts kopš mana pēdējā apmeklējuma",
+       "updatedmarker": "atjaunināts kopš tava pēdējā apmeklējuma",
        "printableversion": "Drukājama versija",
        "permalink": "Pastāvīgā saite",
        "print": "Drukāt",
        "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 komentāru.",
-       "missingcommentheader": "'''Atgādinājums:''' Tu šim komentāram neesi norādījis virsrakstu/tematu.\nJa tu vēlreiz spiedīsi uz \"$1\", tavas izmaiņas tiks saglabātas bez virsraksta.",
+       "missingcommentheader": "<strong>Atgādinājums:</strong> Šim komentāram nav norādīts temats.\nVēlreiz spiežot uz \"$1\", tavs labojums tiks saglabāts bez tā.",
        "summary-preview": "Labojuma kopsavilkuma priekšskatījums:",
        "subject-preview": "Temata pirmskats:",
        "blockedtitle": "Dalībnieks ir bloķēts.",
        "nocreate-loggedin": "Tev nav atļaujas veidot jaunas lapas.",
        "sectioneditnotsupported-title": "Sadaļa rediģēšana nav atbalstīta",
        "sectioneditnotsupported-text": "Sadaļu rediģēsana šajā lapā nav atļauta.",
+       "modeleditnotsupported-title": "Labošana nav atbalstīta",
+       "modeleditnotsupported-text": "Satura modelim \"$1\" labošana nav atbalstīta.",
        "permissionserrors": "Atļauju kļūda",
        "permissionserrorstext": "Tev nav atļauts veikt šo darbību {{PLURAL:$1|šādu iemeslu|šāda iemesla|šādu iemeslu}} dēļ:",
        "permissionserrorstext-withaction": "Tev nav atļauts $2 {{PLURAL:$1|šādu iemeslu|šāda iemesla|šādu iemeslu}} dēļ:",
        "editpage-invalidcontentmodel-text": "Satura modelis \"$1\" nav atbalstīts.",
        "editpage-notsupportedcontentformat-title": "Satura formāts nav atbalstīts",
        "editpage-notsupportedcontentformat-text": "Satura formātu $1 neatbalsta satura modelis $2.",
+       "slot-name-main": "Galvenais",
        "content-model-wikitext": "vikiteksts",
        "content-model-text": "vienkāršs teksts",
        "content-model-javascript": "JavaScript kods",
        "prefixindex": "Meklēt pēc virsraksta pirmajiem burtiem",
        "prefixindex-namespace": "Visas lapas ar prefiksu ($1 vārdtelpa)",
        "prefixindex-submit": "Rādīt",
+       "prefixindex-strip": "Rezultātos paslēpt prefiksu",
        "shortpages": "Īsākās lapas",
        "longpages": "Garākās lapas",
        "deadendpages": "Lapas bez izejošām saitēm",
        "dellogpagetext": "Šajā lapā ir pēdējo dzēsto lapu saraksts.",
        "deletionlog": "dzēšanas reģistrs",
        "log-name-create": "Lapu izveides žurnāls",
+       "logentry-create-create": "$1 {{GENDER:$2|izveidoja}} lapu $3",
        "reverted": "Atjaunots uz iepriekšējo versiju",
        "deletecomment": "Iemesls:",
        "deleteotherreason": "Cits/papildu iemesls:",
        "sessionfailure": "Ir radusies problēma ar sesijas autentifikāciju;\nšī darbība ir atcelta, lai novērstu lietotājvārda iespējami ļaunprātīgu izmantošanu.\nLūdzu, spied \"''back''\" un atjaunini iepriekšējo lapu. Tad mēģini vēlreiz.",
        "changecontentmodel": "Mainīt lapas satura modeli",
        "changecontentmodel-legend": "Mainīt satura modeli",
-       "changecontentmodel-title-label": "Lapas nosaukums",
-       "changecontentmodel-model-label": "Jauns satura modelis",
+       "changecontentmodel-title-label": "Lapas nosaukums:",
+       "changecontentmodel-model-label": "Jaunais satura modelis:",
        "changecontentmodel-reason-label": "Iemesls:",
        "changecontentmodel-submit": "Mainīt",
        "changecontentmodel-success-title": "Satura modelis tika izmainīts",
        "fix-double-redirects": "Automātiski izmainīt visas pāradresācijas, kas ved uz sākotnējo nosaukumu",
        "move-leave-redirect": "Atstāt pāradresāciju",
        "protectedpagemovewarning": "'''Brīdinājums:''' Šī lapa ir aizsargāta, tikai lietotāji ar administratora privilēģijām var to pārvietot.\nPēdējais reģistra ieraksts ir apskatāms zemāk:",
-       "semiprotectedpagemovewarning": "'''Piezīme:''' Šī lapa ir aizsargāta, tikai reģistrētie lietotāji var to pārvietot.\nPēdējais reģistra ieraksts ir apskatāms zemāk:",
+       "semiprotectedpagemovewarning": "<strong>Piezīme:</strong> Šī lapa ir aizsargāta tā, lai tikai pašpārbaudītie lietotāji varētu to pārvietot.\nPēdējais reģistra ieraksts ir apskatāms zemāk:",
        "move-over-sharedrepo": "[[:$1]] jau pastāv koplietotā repozitorijā. Pārvietošana uz šo nosaukumu aizstās koplietoto failu.",
        "file-exists-sharedrepo": "Šis faila nosaukums jau tiek izmantots kopīgajā failu krātuvē.\nLūdzu, izvēlies citu nosaukumu.",
        "export": "Eksportēt lapas",
        "importcantopen": "Nevarēja atvērt importējamo failu",
        "importbadinterwiki": "Slikta starpviki saite",
        "importsuccess": "Importēšana pabeigta!",
-       "importnosources": "Tiešā hronoloģijas augšuplāde ir atslēgta. Nav definēts neviens ''Transwiki'' importa avots (''source'').",
+       "importnosources": "Nav definēta neviena vikivietne, no kuras importēt un tiešā hronoloģijas augšupielāde ir atslēgta.",
        "importnofile": "Neviens importējamais fails netika augšupielādēts.",
        "importuploaderrorsize": "Augšupielādēt importējamo failu neizdevās. \nŠis fails ir lielāks par atļauto augšupielādes lielumu.",
        "importuploaderrorpartial": "Importējamā faila augšupielāde neizdevās.\nFails tika tikai daļēji importēts.",
        "tooltip-feed-atom": "Šīs lapas Atom barotne",
        "tooltip-t-contributions": "{{GENDER:$1|Šī dalībnieka|Šīs dalībnieces}} ieguldījumu uzskaitījums",
        "tooltip-t-emailuser": "Sūtīt e-pastu {{GENDER:$1|šim dalībniekam|šai dalībniecei}}",
+       "tooltip-t-info": "Vairāk informācijas par šo lapu",
        "tooltip-t-upload": "Augšupielādēt failus",
        "tooltip-t-specialpages": "Visu īpašo lapu uzskaitījums",
        "tooltip-t-print": "Drukājama lapas versija",
        "diff-form-submit": "Parādīt atšķirības",
        "permanentlink": "Pastāvīgā saite",
        "permanentlink-revid": "Versijas ID",
+       "permanentlink-submit": "Doties uz versiju",
        "newsection": "Jauna sadaļa",
        "newsection-page": "Mērķa lapa",
+       "newsection-submit": "Doties uz lapu",
        "dberr-problems": "Atvainojiet!\nŠai vietnei ir radušās tehniskas problēmas.",
        "dberr-again": "Uzgaidiet dažas minūtes un pārlādējiet šo lapu.",
        "dberr-info": "(Nevar piekļūt datubāzei: $1)",
        "htmlform-chosen-placeholder": "Izvēlieties iespēju",
        "htmlform-cloner-create": "Pievienot vairāk",
        "htmlform-cloner-delete": "Noņemt",
+       "htmlform-cloner-required": "Vismaz viena vērtība ir obligāta.",
        "htmlform-date-placeholder": "GGGG-MM-DD",
        "htmlform-title-not-creatable": "\"$1\" nav izveidojams lapas nosaukums",
        "htmlform-title-not-exists": "$1 nepastāv.",
        "randomrootpage": "Nejauša saknes lapa",
        "log-action-filter-block": "Bloķēšanas veids:",
        "log-action-filter-protect": "Aizsardzības veids:",
+       "log-action-filter-rights": "Tiesību izmaiņas veids:",
        "log-action-filter-suppress": "Cenzēšanas veids:",
        "log-action-filter-upload": "Augšupielādes veids:",
        "log-action-filter-block-unblock": "Atbloķēšana",
index 12f69f0..b56f065 100644 (file)
@@ -64,6 +64,7 @@
        "tog-norollbackdiff": "Jan tampilan pabedoan sasudah malakukan pangambalian",
        "tog-useeditwarning": "Ingekan denai jikok maninggakan laman suntiang sabalun manyimpan parubahan",
        "tog-prefershttps": "Selalu gunokan koneksi aman katiko masuak log",
+       "tog-showrollbackconfirmation": "Tampilkan konfirmasi katiko mangklik pautan pangambalian",
        "underline-always": "Taruih",
        "underline-never": "Indak pernah",
        "underline-default": "Kulik atau pangaturan paramban web",
        "returnto": "Baliak ka $1",
        "tagline": "Dari {{SITENAME}}",
        "help": "Bantuan",
+       "help-mediawiki": "Bantuan pakaro MediaWiki",
        "search": "Cari",
        "searchbutton": "Cari",
        "go": "Tuju",
        "searcharticle": "Tuju",
        "history": "Riwayaik laman",
-       "history_short": "Riwayaik",
-       "history_small": "riwayaik",
+       "history_short": "Versi",
+       "history_small": "versi",
        "updatedmarker": "alah diubah samanjak kunjuangan tarakhia Sanak",
        "printableversion": "Versi cetak",
        "permalink": "Pautan parmanen",
        "nospecialpagetext": "<strong>Sanak mamintak laman istimewa nan indak sah.</strong>\n\nDaftar laman istimewa nan sah dapek dicaliak di [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "Kasalahan",
        "databaseerror": "Kasalahan basis data",
+       "databaseerror-text": "Ado gangguan pado kueri basis data. Iko mungkin manunjuakkan adonyo kasalahan pado parangkek lunak.",
+       "databaseerror-textcl": "Ado gangguan pado kueri basis data.",
+       "databaseerror-query": "Kueri: $1",
        "databaseerror-function": "Fungsi: $1",
        "databaseerror-error": "تېروتنه: $1",
        "transaction-duration-limit-exceeded": "Untuak mancagah panundoan replikasi nan tinggi, pangiriman ko dibatalan karano lamo panulihan $1 malabiahi bateh $2.\nJiko sanak nio maubah banyak hal dalam sakali ubah, cubo lakuan dalam operasi nan labiah ketek.",
        "cannotdelete-title": "Indak dapek mangapuih laman \"$1\"",
        "delete-scheduled": "Laman \"$1\" dijadwalan untuak diapuih. Mohon basaba.",
        "delete-hook-aborted": "Pengapusan batal jo hook.\nIndak ado keterangan.",
+       "no-null-revision": "Indak dapek mambuek paubahan kosong nan baru untuak laman \"$1\"",
        "badtitle": "Judul indak sah",
        "badtitletext": "Pamintaan judul laman indak sah, kosong, atau antarbaso atau antarwiki nan salah sambuang. Mungkin juo ado kandungan karakter nan indak buliah digunoan untuak judul.",
        "title-invalid-empty": "Judul laman nan dimintak kosong atau hanyo barisi namo sabuah ruang namo.",
        "botpasswords-label-cancel": "Batalan",
        "botpasswords-label-delete": "Hapuih",
        "botpasswords-label-resetpassword": "Setel ulang kato sandi",
+       "botpasswords-label-grants-column": "Izin diagiah",
        "botpasswords-bad-appid": "Namo bot \"$1\" indak sah.",
        "botpasswords-insert-failed": "Gagal manambah namo bot \"$1\". Alah ditambahan sabalun iko?",
        "botpasswords-update-failed": "Gagal mampabarui namo bot \"$1\". Pernah dihapuih sabalunnyo?",
        "botpasswords-updated-body": "Kato sandi untuak bot \"$1\" dari {{GENDER:$2|user}} \"$2\" alah dipabarui.",
        "botpasswords-deleted-title": "Kato sandi bot dihapuih",
        "botpasswords-deleted-body": "Kato sandi untuak bot \"$1\" dari {{GENDER:$2|user}} \"$2\" berhasil dihapuih.",
+       "botpasswords-newpassword": "Kato sandi baru untuak masuak log jo <strong>$1</strong> adolah <strong>$2</strong>. <em>Cataiklah kato sandi ko untuak rujuakan ka muko.</em> <br> (Untuak bot lamo nan mamaralukan namo masuak log nan samo jo namo pangguno, dapek manggunokan <strong>$3</strong> sabagai namo pangguno jo <strong>$4</strong> sabagai kato sandi.)",
+       "botpasswords-no-provider": "BotPasswordsSessionProvider indak tasadio.",
        "botpasswords-restriction-failed": "Bateh dalam kato sandi mangahalangi masuak log ko.",
        "botpasswords-invalid-name": "Namo pangguno nan diagiah indak manganduang pamisah kato sandi bot (\"$1\").",
        "botpasswords-not-exist": "Pangguno \"$1\" indak mampunyoi kato sandi bot banamo \"$2\".",
        "passwordreset-emailelement": "Namo pangguno: \n$1\n\nSandi samantaro: \n$2",
        "passwordreset-emailsentemail": "Jiko alamaik surel ko bahubuangan jo akun Sanak, surel parubahan kato sandi akan dikirim.",
        "passwordreset-emailsentusername": "Jiko ado alamaik surel nan bahubuangan jo namo pangguno ko, surel untuak mangatua ulang kato sandi akan dikirim.",
+       "passwordreset-nocaller": "Paimbau musti disadiokan",
+       "passwordreset-nosuchcaller": "Paimbau indak ado: $1",
+       "passwordreset-ignored": "Pamuliahan kato sandi indak tatangani. Mungkin panyadio indak diatua?",
        "passwordreset-invalidemail": "Alamaik surel indak sah",
        "passwordreset-nodata": "Namo pangguno ataupun alamai surel indak diaagiahan",
        "changeemail": "Tuka atau hapuih alamaik surel.",
        "changeemail-throttled": "Sanak alah acok bana mancubo masuak log. Mohon tunggu $1 sabalun mancubo baliak.",
        "changeemail-nochange": "Mohon masuakan alamaik surel nan lain.",
        "resettokens": "Ubah token",
+       "resettokens-text": "Sanak dapek ma-reset Token nan mamungkinkan akses ka data pribadi tatantu nan takaik jo akun Sanak di siko.\n\nSanak musti malakukannyo kok Sanak sacaro indak sangajo babagi jo urang lain atau kok akun Sanak alah disalinoki.",
+       "resettokens-no-tokens": "Indak ado token untuak di-reset.",
+       "resettokens-tokens": "Token:",
        "resettokens-token-label": "$1 (nilai saat ini:$2)",
+       "resettokens-watchlist-token": "Token untuak sindikasi web (Atom/RSS) dari [[Special:Watchlist|parubahan di daftar pantauan Sanak]]",
+       "resettokens-done": "Reset token.",
+       "resettokens-resetbutton": "Reset token nan dipiliah",
        "bold_sample": "Teks taba",
        "bold_tip": "Teks taba",
        "italic_sample": "Teks miriang",
        "previewerrortext": "Ado nan salah wakatu manunjuakan pratinjau parubahan Sanak.",
        "blockedtitle": "Pangguno diblokir",
        "blocked-email-user": "<strong>Namo pangguno Sanak diblokir untuak mangirim surel. Sanak masih bisa manyuntiang laman lain di wiki ko. </strong> Sanak bisa mancaliak parincian sakek pado [[Special:MyContributions|jariah pangguno]].\n\nSakek dilakuan dek $1.\n\nAlasannyo adolah <em>$2</em>.\n\n* Disakek sajak: $8\n* Sakek kadaluarsa pado: $6\n* Sasaran panyakek: $7\n* ID sakek #$5",
+       "blockedtext-partial": "<strong>Namo pangguno Sanak disakek untuak mangirim surel. Sanak masih bisa manyuntiang laman lain di wiki ko. </strong> Sanak bisa mancaliak parincian sakek pado [[Special:MyContributions|jariah pangguno]].\n\nSakek dilakuan dek $1.\n\nAlasannyo adolah <em>$2</em>.\n\n* Disakek sajak: $8\n* Sakek kadaluarsa pado: $6\n* Sasaran panyakek: $7\n* ID sakek #$5",
        "blockedtext": "'''Namo pangguno atau alamaik IP Sanak alah kanai sakek.'''\n\nSakek dibuek dek $1.\nAlasan nan diagiahan adolah ''$2''.\n\n* Kanai sakek sajak: $8\n* Maso sakek habih pado: $6\n* Sasaran nan disakek: $7\n\nSanak dapek maubungi $1 atau [[{{MediaWiki:Grouppage-sysop}}|panguruih lainnyo]] untuak marundiangan hal ko.\n\nSanak indak dapek manggunoan fitua 'Kirim surel ka pangguno ko' kacuali Sanak alah mamasuakan alamaik surel nan sah di [[Special:Preferences|pangaturan akun]] dan Sanak indak sadang disakek untuak manggunoannyo.\n\nAlamaik IP Sanak adolah $3, dan ID panyakek adolah $5.\nTolong saratoan informasi di ateh pado satiok patanyoan nan Sanak buek.",
        "autoblockedtext": "Alamaik IP Sanak alah kanai sakek sacaro otomatih dek dipakai jo pangguno lain, nan alah disakek dek $1. Alasannyo dek:\n\n:<em>$2</em>\n\n* Kanai sakek sajak: $8\n* Maso sakek habih pado: $6\n* Sasaran nan disakek: $7\n\nSanak dapek maubuangi $1 atau [[{{MediaWiki:Grouppage-sysop}}|panguruih lainnya]] untuak marundiangan pakaro ko.\n\nSanak indak dapek manggunoan pakakeh \"{{int:emailuser}}\" kacuali Sanak alah mamasuakan alamaik surel nan sah pado [[Special:Preferences|pangaturan akun]] dan Sanak indak sadang disakek untuak manggunoannyo.\n\nAlamaik IP Sanak adolah $3, dan ID panyakekan adolah $5.\nTolong saratoan informasi di ateh pado satiok patanyaan nan Sanak buek.",
+       "systemblockedtext": "Namo pangguno atau alamaik IP Sanak alah disakek sacaro otomatis dek MediaWiki.\nAlasan nan diagiah adolah:\n\n:<em>$2</em>\n\n* Disakek sajak: $8\n* Sakek kadaluwarsa pado: $6\n* Sasaran panyakekan: $7\n\nAlamaik IP Sanak kini adolah $3\nMohon saratokan sadoalah parincian di ateh dalam satiok patanyoan nan Sanak ajukan.",
        "blockednoreason": "indak ado alasan nan diagiah.",
+       "blockedtext-composite-ids": "Panyakekan ID relevan: $1 (alamaik IP Sanak juo dapek dicekal)",
+       "blockedtext-composite-no-ids": "Alamaik IP Sanak muncua dalam daftar itam gando",
+       "blockedtext-composite-reason": "Ado panyakekan bagando ka bakeh akun Sanak dan/atau alamaik IP Sanak.",
        "whitelistedittext": "Sanak musti $1 untuak manyuntiang laman.",
        "confirmedittext": "Sanak musti mangkonfirmasian alamaik surel sabalun manyuntiang laman.\nMasuakan dan validasian alamaik surel Sanak pado [[Special:Preferences|pangaturan pangguno]] Sanak.",
        "nosuchsectiontitle": "Bagian indak ditamuan",
        "userjsonyoucanpreview": "<strong>Tip:</strong> Gunoan tombol \"{{int:showpreview}}\" untuak mauji JSON baharu Sanak sabalun manyimpannyo.",
        "userjsyoucanpreview": "'''Tips:''' Gunoan tombol \"{{int:showpreview}}\" untuak mauji JS baharu Sanak sabalun manyimpannyo.",
        "usercsspreview": "<strong>Ingeklah bahawa Sanak sadang manampilan pratinjau dari CSS Sanak.\nPratinjau ko alun disimpan!</strong>",
+       "userjsonpreview": "<strong>Ingeklah baso nan Sanak caliak anyolah pratonton JavaScript Sanak, dan pratonton tasabuik alun disimpan!</strong>",
        "userjspreview": "<strong>Ingeklah bahawa nan Sanak liek hanyolah pratinjau JavaScript Sanak, dan pratinjau tasabuik alun disimpan!</strong>",
        "sitecsspreview": "<strong>Ingeklah Sanak hanyo manampilan pratinjau dari CSS ko. Parubahan alun disimpan!</strong>",
        "sitejsonpreview": "<strong>Ingeklah bahwa Sanak hanyo manampilan pratinjau konfigurasi JSON ko. Parubahan alun basimpan!</strong>",
        "yourtext": "Teks Sanak",
        "storedversion": "Versi tasimpan",
        "editingold": "'''Paringatan:\nSanak manyuntiang revisi lamo suatu laman.\nJikok Sanak manyimpannyo, parubahan-parubahan nan dibuek sajak revisi ko akan hilang.'''",
+       "unicode-support-fail": "Tampaknyo masin pancari Sanak indak mandukuang Unicode, nan manjadi syaraik panyuntiangan laman. Jadi suntiangan Sanak indak disimpan.",
        "yourdiff": "Pambedoan",
        "copyrightwarning": "Untuak diingek bahaso apo nan disumbang kapado {{SITENAME}} dianggap lah dilapeh di bawah $2 (caliak $1 untuak langkoknyo).\nJikok awak indak ingin apo nan ditulih tu disuntiang dan disebaran, jan dikirim tulisan tu ka siko.<br />\nAwak musti bajanji juo bahaso iko adolah asia karya awak surang, atau disalin dari sumber miliak basamo atau sumber bebas lainnyo.\n'''Jan dikirim karya bahak cipta nan indak baizin!'''",
        "copyrightwarning2": "Parhatikan sadoalah jariah tahadok {{SITENAME}} dapek disuntiang, diubah, atau dihapuih dek panyumbang lainnyo. Jikok Sanak indak ingin tulisan Sanak disuntiang urang lain, jan kiriman ka siko.<br />Sanak juo bajanji iko adolah hasil karya Sanak surang, atau disalin dari sumber miliak umum atau sumber bebas nan lain (liek $1 untuak informasi labiah lanjuik). '''JAN KIRIMAN KARYA NAN DILINDUNGI HAK CIPTA TANPA IJIN!'''",
        "nocreate-loggedin": "Sanak ndak mampunyoi hak akses untuak mambuek laman baharu.",
        "sectioneditnotsupported-title": "Panyuntiangan bagian indak didukuang",
        "sectioneditnotsupported-text": "Panyuntiangan bagian indak didukuang di laman suntiang iko.",
+       "modeleditnotsupported-title": "Panyuntiangan indak didukuang",
+       "modeleditnotsupported-text": "Panyuntiangan indak didukuang untuak model konten $1.",
        "permissionserrors": "Kasalahan Hak Akses",
        "permissionserrorstext": "Sanak indak ado hak untuak malakuannyo dek {{PLURAL:$1|alasan}} barikuik:",
        "permissionserrorstext-withaction": "Sanak indak punyo hak akses untuak $2, dek {{PLURAL:$1|alasan}} barikuik:",
        "edit-no-change": "Suntiangan sanak ditulak, karano indak ado parubahan nan tajadi ka teks.",
        "edit-slots-cannot-add": "{{PLURAL:$1|slot is|slots are}} barikuik indak didukuang disiko: $2.",
        "edit-slots-cannot-remove": "{{PLURAL:$1|slot is|slots are}} wajib dan indak  buliah dihapuih: $2.",
+       "edit-slots-missing": "{{PLURAL:$1|slot is|slots are}} barikuik indak didukuang disiko: $2.",
        "postedit-confirmation-created": "Laman alah dibuek.",
        "postedit-confirmation-restored": "Laman alah dipuliahan.",
        "postedit-confirmation-saved": "Suntiangan Sanak alah tasimpan.",
        "invalid-content-data": "Data kanduangan indak valid.",
        "content-not-allowed-here": "Isi \"$1\" indak diizinkan di laman [[:$2]] pado slot \"$3\"",
        "editwarning-warning": "Maninggakan laman ko dapek maakibaikan parubahan nan dibuek hilang. Jikok Sanak lah masuak log, dapek mamatian pasan ko malalui bagian \"{{int:prefs-editing}}\" pado laman Pangaturan.",
+       "editpage-invalidcontentmodel-title": "Model konten indak didukuang",
+       "editpage-invalidcontentmodel-text": "Model konten \"$1\" indak didukuang.",
+       "editpage-notsupportedcontentformat-title": "Format konten indak didukuang",
+       "editpage-notsupportedcontentformat-text": "Format konten $1 indak didukuang dek model konten $2.",
        "slot-name-main": "Utamo",
        "content-model-wikitext": "Teks wiki",
        "content-model-text": "Teks kosong",
        "content-model-css": "CSS",
        "content-json-empty-object": "Objek kosong",
        "content-json-empty-array": "Lariak kosong",
+       "unsupported-content-model": "<strong> Paringatan: </strong> Model konten $1 indak didukuang di wiki ko.",
+       "unsupported-content-diff": "Panyuntiangan indak didukuang untuak model konten $1.",
+       "unsupported-content-diff2": "Pabedaan antaro model konten $1 jo $2 indak didukuang di wiki ko.",
        "deprecated-self-close-category": "Laman nan menggunoan tag HTML tatutuik-surang indak sah",
+       "deprecated-self-close-category-desc": "Laman ko manganduang tag HTML tatutuik-surang nan indak sah, sarupo <code>&lt;b/></code> atau <code>&lt;span/></code>.  Parilaku tag sarupo ko ka sagiro barubah supayo konsisten jo spesifikasi HTML5, jadi panggunoannyo dalam teks wiki indak lai disarankan.",
        "expensive-parserfunction-warning": "'''Paringatan:''' Laman ko manganduang talalu banyak panggilan fungsi parser.\n\nSeharusnyo kurang dari $2 {{PLURAL:$2|panggilan}}, tapi {{PLURAL:$1|kini ado $1 panggilan}}.",
        "expensive-parserfunction-category": "Laman nan talalu banyak panggilan fungsi parser",
        "post-expand-template-inclusion-warning": "'''Peringatan:''' Ukuran templat talalu gadang.\nBabarapo templat akan diabaikan.",
        "undo-failure": "Suntiangan ko indak dapek dibatalan dek konflik panyuntiangan antaro.",
        "undo-norev": "Suntiangan ko indak dapek dibatalan dek laman indak ditamukan atau lah dihapuih.",
        "undo-summary": "Mambatalan revisi $1 oleh [[Special:Contributions/$2|$2]] ([[User talk:$2|maota]])",
+       "undo-summary-anon": "Baliakan revisi $1 dek [[Special:Contributions/$2|$2]]",
        "cantcreateaccount-text": "Mambuek akun dari alamat IP ko ('''$1''') alah diblok jo [[User:$3|$3]].\n\nAlasan nan diagiah jo $3 adolah ''$2''",
        "viewpagelogs": "Caliak log untuak laman ko",
        "nohistory": "Indak ado sajarah panyuntiangan untuak laman ko",
        "action-writeapi": "manggunoan panulisan API",
        "action-import": "impor laman dari wiki lain",
        "nchanges": "$1 {{PLURAL:$1|parubahan}}",
-       "enhancedrc-history": "riwayaik",
+       "enhancedrc-history": "versi",
        "recentchanges": "Parubahan baru",
        "recentchanges-legend": "Piliahan parubahan baru",
        "recentchanges-summary": "Caliak parubahan baru di wiki pado laman ko.<br />\n;Patunjuak:(<span style=\"color:blue;\">bedo</span>) parubahan, (<span style=\"color:blue;\">sijarah</span>) riwayaik parubahan, '''B''' laman baru, '''b''' suntiangan bot, '''k''' suntiangan ketek, <span class=\"unpatrolled\">!</span> parubahan alun dipatroli,<br /><span style=\"color:green;\">'''(+ ''bita'')'''</span> isi laman batambah, <span style=\"color:red;\">(- ''bita'')</span> isi laman bakurang, (← Ikhtisar otomatih), (→ <span style=\"color:grey;\">Suntiangan bagian</span>)",
index e63cd39..37611e2 100644 (file)
@@ -71,6 +71,7 @@
        "tog-useeditwarning": "Предупреди ме кога сакам да напуштам страница за уредување без да ги имам зачувано промените",
        "tog-prefershttps": "Секогаш најавувај ме преку безбедна врска",
        "tog-showrollbackconfirmation": "Прикажи потврдница при стискање на врската за отповикување",
+       "tog-requireemail": "Барај е-пошта за ставање нова лозинка",
        "underline-always": "Секогаш",
        "underline-never": "Никогаш",
        "underline-default": "Според рувото или прелистувачот",
        "undo-norev": "Измената не можеше да биде вратена бидејќи не постои или била избришана.",
        "undo-nochange": "Се чини дека измената (уредувањето) е веќе вратена.",
        "undo-summary": "Откажано уредувањето $1 на уредникот [[Special:Contribs/$2|$2]] ([[User talk:$2|разговор]])",
+       "undo-summary-anon": "Отповикај ја преработката $1 на [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Поништи ја преработката $1 на скриен корисник",
        "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>",
        "prefs-help-email": "Е-поштата е незадолжителна, но ќе ви треба за добивање на нова лозинка ако си ја заборавите постоечката.",
        "prefs-help-email-others": "Можете да изберете другите да ве контактираат преку вашата корисничка страница без да го откриете вашиот идентитет.",
        "prefs-help-email-required": "Е-поштенска адреса е задолжително да се наведе.",
+       "prefs-help-requireemail": "Ако е штиклирано, можноста за нова лозинка ќе ја имаат само корисниците што навеле корисничко име и е-пошта.",
        "prefs-info": "Основни информации",
        "prefs-i18n": "Јазик",
        "prefs-signature": "Потпис",
        "cantrollback": "Уредувањето не може да се отповика.\nПоследниот уредник е воедно и единствениот автор на страницата.",
        "alreadyrolled": "Не може да се отповика последното уредување на страницата „[[:$1]]“ извршено од  [[User:$2|$2]] ([[User talk:$2|разговор]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);\nнекој друг веќе ја изменил или отповикал страницата.\n\nПоследното уредување го изврши [[User:$3|$3]] ([[User talk:$3|разговор]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Коментарот на уредувањето беше: <em>$1</em>.",
-       "revertpage": "Отстрането уредувањето на [[Special:Contributions/$2|$2]] ([[User talk:$2|разговор]]), вратено на последната верзија на [[User:$1|$1]]",
+       "revertpage": "Отповикани уредувањата на [[Special:Contributions/$2|$2]] ([[User talk:$2|разговор]]), враќајќи на последната преработка на [[User:$1|$1]]",
+       "revertpage-anon": "Отповикани уредувања на [[Special:Contributions/$2|$2]], враќајќи на последната преработка на [[User:$1|$1]]",
        "revertpage-nouser": "Вратени уредувања од скриен корисник на последната преработка на {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Откажани уредувањата на {{GENDER:$3|$1}};\nвратено на последната верзија на {{GENDER:$4|$2}}.",
        "sessionfailure-title": "Седницата не успеа",
        "ipblocklist-legend": "Најди блокиран корисник",
        "blocklist-userblocks": "Скриј блокирања на корис. сметки",
        "blocklist-tempblocks": "Скриј привремени блокирања",
+       "blocklist-indefblocks": "Скриј бесконечни блокови",
        "blocklist-addressblocks": "Скри блокирања на поединечни IP-адреси",
        "blocklist-type": "Вид:",
        "blocklist-type-opt-all": "Сите",
index 7540d5c..17a46a4 100644 (file)
        "ok": "ꯌꯥꯔꯦ",
        "retrievedfrom": "\"$1\" ꯃꯐꯝꯗꯨꯗꯒꯤ ꯑꯣꯏꯔꯛꯄꯥ",
        "youhavenewmessages": "{{PLURAL:$3|ꯅꯪꯉꯣꯟꯗ ꯂꯩ}} $1 ($2) ꯫",
-       "youhavenewmessagesfromusers": "{{PLURAL:$4|You have}} $1 from {{PLURAL:$3|another user|$3 users}} ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|ꯅꯪꯅꯥ}} $1 ꯗꯒꯤ {{PLURAL:$3|ꯑꯇꯣꯞꯄ ꯁꯤꯖꯤꯟꯅꯔꯤꯕ|$3 ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯁꯤꯡ}} ($2).",
        "youhavenewmessagesmanyusers": "ꯅꯪ $1 ꯂꯩꯔꯦ $2 ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥ ꯃꯌꯥꯝꯗꯒꯤ ꯫",
        "newmessageslinkplural": "{{PLURAL:$1|ꯑꯅꯧꯕ ꯄꯥꯎꯖꯦꯜ ꯱|꯹꯹꯹=ꯑꯅꯧꯕ ꯄꯥꯎꯖꯦꯜꯁꯤꯡ}}",
        "newmessagesdifflinkplural": "ꯑꯔꯣꯏꯕꯥ {{PLURAL:$1|ꯑꯍꯣꯡꯕ|꯹꯹꯹=ꯑꯍꯣꯡꯕꯁꯤꯡ}}",
        "showdiff": "ꯑꯍꯣꯡꯕꯗꯨ ꯎꯨꯠꯂꯨ",
        "blankarticle": "<strong>Warning:</strong> The page you are creating is blank.\nIf you click \"$1\" again, the page will be created without any content.",
        "anoneditwarning": "<strong>Warning:</strong> ꯅꯪ ꯃꯅꯨꯡ ꯆꯪꯗꯔꯤ꯬꯬ ꯫ Your IP address will be publicly visible if you make any edits. If you <strong>[$1 log in]</strong> or <strong>[$2 create an account]</strong>, your edits will be attributed to your username, along with other benefits.",
-       "loginreqlink": "Chang Sinba",
+       "blockedtext": "<strong>ꯅꯪꯒꯤ ꯁꯤꯖꯤꯟꯅꯔꯤꯕ-ꯃꯃꯤꯡ ꯅꯠꯇꯔꯒ ꯑꯥꯏꯄꯤ ꯑꯦꯗꯔꯦꯁ ꯑꯁꯤ ꯊꯤꯡꯖꯤꯟꯈꯔꯦ ꯫ </strong>\n\nꯑꯊꯤꯡꯕ ꯑꯁꯤ $1ꯅꯥ ꯁꯦꯝꯕꯅꯤ ꯫\nꯃꯔꯝꯗꯨ ꯃꯁꯤꯗ ꯄꯤꯔꯦ<em>$2</em>.\n\n* ꯊꯤꯡꯕ ꯍꯧꯕ: $8\n* ꯊꯤꯡꯕ ꯂꯣꯏꯕ ꯃꯇꯝ: $6\n* ꯑꯇꯝꯅꯅ ꯊꯤꯡꯕ: $7\n\nꯅꯪꯅꯥ $1 ꯄꯥꯎ ꯐꯥꯎꯅꯕ ꯌꯥꯅꯤ ꯅꯠꯇꯔꯒ ꯑꯇꯣꯞꯄ  [[{{MediaWiki:Grouppage-sysop}}|ꯆꯨꯞꯂꯤꯄꯥꯏꯔꯤꯕꯁꯤꯡ]]ꯗ ꯑꯊꯤꯡꯕꯗꯨꯒꯤ ꯃꯇꯥꯡꯗ ꯈꯟꯅ ꯅꯩꯅꯕ ꯫\nꯅꯪꯅꯥ ꯁꯤꯖꯤꯟꯅꯕ ꯌꯥꯔꯣꯏ \"{{int:emailuser}}\" ꯅꯪꯒꯤ ꯑꯦꯀꯥꯎꯟꯗꯨꯒꯤ ꯏꯃꯦꯜ ꯑꯦꯗꯔꯦꯁ ꯑꯃꯥ ꯍꯥꯞꯇ꯭ꯔꯤꯈꯩ [[Special:Preferences|ꯑꯦꯀꯥꯎꯟ ꯀꯔꯝꯕꯗ ꯈꯟꯒꯅꯤ]] ꯑꯃꯁꯨꯡ ꯃꯗꯨꯗꯗꯤ ꯁꯤꯖꯤꯟꯅꯕꯗ ꯊꯤꯡꯗꯦ ꯫\nꯅꯪꯒꯤ ꯍꯧꯖꯤꯛ ꯑꯥꯏꯄꯤ ꯑꯦꯗꯔꯦꯁ ꯁꯤ $3ꯅꯤ, ꯑꯃꯁꯨꯡ ꯊꯤꯡꯈꯤꯕ ꯑꯥꯏꯗꯤ ꯅꯥ #$5ꯅꯤ ꯫\nꯆꯥꯟꯕꯤꯗꯨꯅꯥ ꯃꯊꯛꯀꯤ ꯑꯀꯨꯞꯄ ꯃꯔꯣꯜꯁꯤ ꯌꯥꯎꯍꯟꯂꯨ ꯅꯪꯅꯥ ꯆꯪꯕ ꯈꯨꯗꯤꯡꯗ ꯫",
+       "loginreqlink": "ꯆꯪꯕ",
        "accmailtitle": "ꯄꯥꯁꯋ꯭ꯔꯇ ꯊꯥꯕ",
        "newarticle": "(ꯑꯅꯧꯕꯥ)",
        "newarticletext": "You have followed a link to a page that does not exist yet.\nTo create the page, start typing in the box below (see the [$1 help page] for more info).\nIf you are here by mistake, click your browser's <strong>ꯍꯟꯕ</strong> button.",
        "noarticletext-nopermission": "There is currently no text in this page.\nYou can [[Special:Search/{{PAGENAME}}|search for this page title]] in other pages, or <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} search the related logs]</span>, but you do not have permission to create this page.",
        "missing-revision": "The revision #$1 of the page named \"{{FULLPAGENAME}}\" does not exist.\n\nThis is usually caused by following an outdated history link to a page that has been deleted.\nDetails can be found in the [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} deletion log].",
        "userpage-userdoesnotexist-view": "$1 ꯁꯤꯖꯤꯟꯅꯔꯤꯕ ꯑꯦꯀꯥꯎꯅ ꯁꯤ ꯃꯤꯡ ꯆꯟꯗꯔꯤ ꯫",
+       "clearyourcache": "<strong>ꯏꯁꯤꯟꯒꯗꯕ:</strong> ꯇꯨꯡꯁꯤꯟꯂꯕ ꯃꯇꯨꯡ, ꯅꯪꯅꯥ ꯑꯍꯣꯡꯕ ꯎꯅꯕ ꯅꯪꯒꯤ ꯕꯔꯥꯎꯁꯔ ꯀꯥꯆꯦ ꯕꯥꯏꯄꯥꯁ ꯇꯧꯔꯣ ꯫\n* <strong>ꯐꯥꯌꯥꯔꯐꯣꯛꯁ / ꯁꯐꯥꯔꯤ:</strong> ꯄꯥꯏꯁꯤꯟꯕ<em>ꯊꯥꯡꯇꯣꯛꯄ</em> ꯅꯝꯃꯤꯉꯩ ꯃꯅꯨꯡꯗ<em>ꯑꯃꯨꯛꯍꯟꯅ-ꯆꯤꯡꯉꯣ</em>, ꯅꯠꯇꯔꯒ ꯅꯝꯃꯣ <em>Ctrl-F5</em> ꯑꯃꯥ ꯍꯦꯛꯇꯥ ꯅꯠꯃꯣ <em>Ctrl-R</em> (<em>⌘-R</em> ꯃꯦꯛ ꯱ ꯇꯥ)\n* <strong>ꯒꯨꯒꯜ ꯀꯔꯣꯝ:</strong> ꯅꯝꯃꯣ <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> ꯃꯦꯛ ꯱ ꯗ)\n* <strong>ꯏꯟꯇꯔꯅꯦꯠ ꯑꯦꯛꯁꯄ꯭ꯂꯣꯔꯔ:</strong> ꯄꯥꯏꯁꯤꯟꯕ <em>Ctrl</em> ꯅꯝꯃꯤꯉꯩ ꯃꯅꯨꯡꯗ <em>ꯇꯦꯈꯠꯍꯟꯂꯨ</em>, ꯅꯠꯇꯔꯒr ꯅꯝꯃꯨ <em>Ctrl-F5</em>\n* <strong>ꯑꯣꯄꯦꯔꯥ:</strong> ꯑꯗꯨꯗ ꯆꯠꯂꯨ <em>ꯃꯤꯅꯨ → ꯁꯦꯝꯐꯝ</em> (<em>ꯑꯣꯄꯦꯔꯥ → ꯀꯔꯝꯕꯗ ꯄꯤꯒꯅꯤ</em> ꯃꯦꯛ ꯱ ꯗꯥ) ꯑꯃꯁꯨꯡ ꯑꯗꯨꯒꯥ <em>ꯑꯔꯣꯟꯕ ꯱ꯁꯨꯡ ꯉꯥꯛꯁꯦꯟ → ꯕꯔꯥꯎꯁꯔ ꯗꯥꯇꯥ ꯀꯣꯛꯊꯣꯛꯄ → ꯀꯥꯆꯦ ꯃꯤꯔꯦꯜꯁꯤꯡ ꯑꯃꯁꯨꯡ ꯐꯥꯏꯜꯁꯤꯡ</em> ꯗꯥ ꯫",
        "updated": "(ꯅꯧꯊꯣꯛꯍꯟꯂꯦ)",
        "note": "<strong>ꯏꯁꯤꯟꯒꯗꯕ:</strong>",
        "continue-editing": "ꯁꯦꯝꯒꯠꯄꯒꯤ ꯃꯐꯝꯗꯨꯗꯥ ꯆꯠꯂꯨ",
        "yourdiff": "ꯈꯦꯠꯅꯕꯥꯁꯤꯡ",
        "copyrightwarning": "Please note that all contributions to {{SITENAME}} are considered to be released under the $2 (see $1 for details).\nIf you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.<br />\nYou are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource.\n<strong>Do not submit copyrighted work without permission!</strong>",
        "templatesused": "ꯃꯁꯤꯒꯤ ꯂꯃꯥꯏꯁꯤꯗ ꯁꯤꯖꯤꯟꯅꯕ {{PLURAL:$1|ꯇꯦꯝꯄꯂꯦꯠ|ꯇꯦꯝꯄꯂꯦꯠꯁꯤꯡ}}:",
-       "templatesusedpreview": "{{PLURAL:$1|ꯇꯦꯝꯄꯂꯦꯠ|ꯇꯦꯝꯄꯂꯦꯠꯁꯤꯡ}} ꯄꯔꯤꯕꯤꯌꯨ ꯗ ꯁꯤꯖꯤꯟꯅꯕ:",
+       "templatesusedpreview": "{{PLURAL:$1|ê¯\87ꯦê¯\9dê¯\84ê¯\82ꯦꯠ|ê¯\87ꯦê¯\9dê¯\84ê¯\82ꯦꯠê¯\81ꯤꯡ}} ê¯\83ê¯\81ꯤê¯\92ꯤ ê¯\84ê¯\94ꯤê¯\95ꯤê¯\8cꯨ ê¯\97 ê¯\81ꯤê¯\96ꯤê¯\9fê¯\85ê¯\95:",
        "template-protected": "(ꯉꯥꯛꯊꯣꯛꯂꯕꯥ)",
        "template-semiprotected": "(ꯇꯪꯈꯥꯏ ꯉꯥꯛꯊꯣꯛꯂꯕꯥ)",
        "hiddencategories": "This page is a member of {{PLURAL:$1|1 hidden category|$1 hidden categories}}:",
        "histlast": "ꯑꯅꯧꯕꯥ",
        "historyempty": "(ꯑꯍꯥꯡꯕ)",
        "history-feed-title": "ꯄꯨꯋꯥꯔꯤ ꯑꯃꯨꯛ ꯍꯟꯅ ꯌꯦꯡꯕ",
+       "history-feed-description": "ꯋꯤꯀꯤꯗ ꯃꯁꯤꯒꯤ ꯂꯃꯥꯏꯁꯤꯒꯤ ꯑꯃꯨꯛꯍꯟꯅ-ꯌꯦꯡꯕ ꯄꯨꯋꯥꯔꯤ",
        "history-feed-item-nocomment": "$2 ꯗ$1",
        "rev-delundel": "ꯑꯍꯣꯡꯕꯥ ꯎꯍꯟꯂꯤꯕꯥ",
        "rev-showdeleted": "ꯎꯨꯠꯂꯨ",
        "nextn": "ꯃꯥꯊꯪ{{PLURAL:$1|$1}}",
        "prev-page": "ꯃꯃꯥꯡꯒꯤ ꯂꯃꯥꯏ",
        "next-page": "ꯃꯊꯪ ꯂꯃꯥꯏ",
-       "prevn-title": "ꯃꯃꯥꯡꯒꯤ $1 {{PLURAL:$1|result|results}}",
+       "prevn-title": "ꯃꯃꯥꯡꯒꯤ $1 {{PLURAL:$1|ꯑꯣꯏꯅꯥ ꯐꯪꯕ|ꯑꯣꯏꯅꯥ ꯐꯪꯉꯦ}}",
        "nextn-title": "ꯃꯊꯪ $1 {{PLURAL:$1|ꯐꯣꯜ|ꯐꯣꯜꯁꯤꯡ}}",
        "shown-title": "ꯎꯠꯂꯨ $1 {{PLURAL:$1|result|results}} ꯂꯃꯥꯏ ꯑꯃꯝ ꯑꯃꯝꯒꯤ ꯑꯣꯏꯅꯥ",
        "viewprevnext": "ꯎꯨꯇꯂꯨ ($1 {{int:pipe-separator}} $2) ($3)",
        "search-relatedarticle": "ꯃꯔꯤꯂꯩꯅꯔꯦ",
        "searchrelated": "ꯃꯔꯤꯂꯩꯅꯔꯦ",
        "searchall": "ꯄꯨꯂꯞ",
-       "search-showingresults": "{{PLURAL:$4|Result <strong>$1</strong> of <strong>$3</strong>|Results <strong>$1 – $2</strong> of <strong>$3</strong>}}",
+       "search-showingresults": "{{PLURAL:$4| ꯑꯣꯏꯅꯥ ꯐꯪꯕ <strong>$1</strong> ꯒꯤ <strong>$3</strong>|ꯑꯣꯏꯅꯥ ꯐꯪꯕꯁꯤꯡ<strong>$1 – $2</strong> ꯒꯤ <strong>$3</strong>}}",
        "search-nonefound": "ꯃꯁꯤꯒꯤ ꯐꯣꯜꯁꯤꯒꯥ ꯆꯥꯟꯅꯕꯥ ꯂꯩꯇꯦ ꯫",
        "powersearch-legend": "ꯈꯨꯃꯥꯡ ꯆꯥꯎꯁꯤꯟꯅ ꯊꯤꯕꯥ",
        "powersearch-togglelabel": "ꯑꯁꯣꯏ ꯑꯔꯥꯟ ꯌꯥꯎꯕꯔ ꯌꯦꯡꯕ:",
        "right-read": "ꯂꯃꯥꯏꯁꯤꯡ ꯄꯥꯕꯥ",
        "right-edit": "ꯂꯃꯥꯏꯁꯤꯡ ꯁꯦꯝꯒꯠꯄ",
        "right-writeapi": "API sijinaduna eba",
-       "newuserlogpage": "ꯁꯤꯖꯤꯅꯅꯔꯤꯕ creation log",
+       "newuserlogpage": "ꯁꯤꯖꯤꯟꯅꯔꯤꯕ ꯆꯪꯕꯗꯨ ꯁꯥꯕ",
+       "rightslog": "ꯁꯤꯖꯤꯟꯅꯔꯤꯕ ꯆꯪꯕ ꯍꯛꯁꯤꯡ",
        "action-edit": "ꯃꯁꯤꯒꯤ ꯂꯃꯥꯏꯁꯤ ꯁꯦꯝꯒꯠꯂꯨ",
        "action-createaccount": "ꯃꯁꯤ ꯁꯤꯖꯤꯟꯅꯔꯤꯕ ꯑꯦꯀꯥꯎꯟ ꯁꯤ ꯁꯦꯝꯃꯨ",
        "enhancedrc-history": "ꯄꯨꯋꯥꯔꯤ",
        "recentchanges-label-unpatrolled": "ꯃꯁꯤꯒꯤ ꯁꯦꯝꯒꯠꯄꯁꯤ ꯍꯧꯖꯤꯛꯐꯥꯎ ꯌꯦꯡꯁꯤꯟꯗ꯭ꯔꯤ",
        "recentchanges-label-plusminus": "ꯕꯥꯏꯠꯀꯤ ꯑꯍꯣꯡꯕꯒꯤ ꯃꯇꯪ ꯏꯟꯅꯥ ꯂꯥꯃꯥꯏꯁꯤꯒꯤ ꯑꯆꯧꯕꯥ ꯂꯦꯞꯄꯤ",
        "recentchanges-legend-heading": "<strong>ꯊꯥꯏꯅꯗꯒꯤ</strong>",
-       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (also see [[Special:NewPages|ꯑꯅꯧꯕ ꯂꯃꯥꯏꯁꯤꯡ ꯄꯔꯤꯡ]])",
+       "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} (ꯁꯤꯁꯨ ꯌꯦꯡꯉꯨ [[Special:NewPages|ꯑꯅꯧꯕ ꯂꯃꯥꯏꯁꯤꯡ ꯄꯔꯤꯡ]])",
        "rcnotefrom": "ꯃꯈꯥ {{PLURAL:$5|is the change|are the changes}} since <strong>$3, $4</strong> (up to <strong>$1</strong> shown).",
        "rclistfrom": "$2$3 ꯁꯤꯗꯒꯤ ꯍꯧꯔꯒꯥ ꯑꯅꯧꯕꯥ ꯑꯍꯣꯡꯕꯗꯨ ꯎꯨꯇꯂꯨ",
        "rcshowhideminor": "$1 ꯄꯤꯛꯅꯥ ꯁꯦꯝꯒꯠꯄꯁꯤꯡ",
        "filehist-comment": "ꯑꯄꯥꯝꯕꯥ ꯐꯣꯡꯗꯣꯛ ꯎ",
        "imagelinks": "ꯐꯥꯏꯜꯒꯤ ꯁꯤꯖꯤꯟꯅꯐꯝ",
        "linkstoimage": "ꯃꯇꯨꯡ ꯏꯟꯕ {{PLURAL:$1|ꯂꯃꯥꯏꯁꯤꯖꯤꯟꯅꯕ|$1ꯂꯃꯥꯏ ꯁꯤꯖꯤꯟꯅꯕ}} ꯃꯁꯤꯒꯤ ꯐꯥꯏꯜ:",
-       "linkstoimage-more": "$1 ê¯\97ê¯\92ꯤ ê¯\8dꯦê¯\9fê¯\85 {{PLURAL:$1|ê¯\82ê¯\83ꯥê¯\8f ê¯\81ꯤê¯\96ꯤê¯\9fê¯\85ê¯\90ê¯\9d|page use}} ê¯\83ê¯\81ꯤ ê¯\90ꯥê¯\8fê¯\9c ê¯«\nThe following list shows the {{PLURAL:$1|ê¯\91ê¯\8dꯥê¯\9fê¯\95 ê¯\82ê¯\83ꯥê¯\8f|first $1 pages}} that use this file only.\nA [[Special:WhatLinksHere/$2|ꯄꯔꯤꯡ ꯄꯨꯂꯞ]] ꯁꯤ ꯐꯪꯉꯦ ꯫",
+       "linkstoimage-more": "$1 ê¯\97ê¯\92ꯤ ê¯\8dꯦê¯\9fê¯\85 {{PLURAL:$1|ê¯\82ê¯\83ꯥê¯\8f ê¯\81ꯤê¯\96ꯤê¯\9fê¯\85ê¯\95ê¯\81ꯤꯡ|ê¯\82ê¯\83ꯥê¯\8f ê¯\81ꯤê¯\96ꯤê¯\9fê¯\85ê¯\95}} ê¯\83ê¯\81ꯤê¯\92ꯤ ê¯\90ꯥê¯\8fê¯\9cê¯\81ꯤê¯\97 ê¯«\nê¯\83ê¯\88ꯥê¯\92ꯤê¯\81ꯤê¯\85ꯥ ê¯\84ê¯\94ꯤꯡê¯\81ꯤê¯\85ꯥ ê¯\8eꯠê¯\82ꯤê¯\95ê¯\81ꯤ {{PLURAL:$1|ê¯\91ê¯\8dꯥê¯\9fê¯\95 ê¯\82ê¯\83ꯥê¯\8f|ê¯\91ê¯\8dꯥê¯\9fê¯\95 $1 ê¯\82ê¯\83ꯥê¯\8fê¯\81ꯤꯡ}} ê¯\90ꯥê¯\8fê¯\9c ê¯\81ꯤê¯\96ꯤê¯\9fê¯\85ê¯\95 ê¯\88ꯧê¯\87ê¯\85ꯤ ê¯«\n[[Special:WhatLinksHere/$2|ꯄꯔꯤꯡ ꯄꯨꯂꯞ]] ꯁꯤ ꯐꯪꯉꯦ ꯫",
        "nolinkstoimage": "ꯃꯁꯤꯒꯤ ꯐꯥꯏꯜ ꯁꯤ ꯁꯤꯖꯤꯟꯅꯕ ꯂꯃꯥꯏꯁꯤꯡ ꯂꯩꯇꯦ ꯫",
        "linkstoimage-redirect": "$1 (ꯐꯥꯏꯜ ꯱ꯗꯒꯤ ꯱ ꯗ ꯂꯥꯛꯍꯟꯕ) $2",
        "sharedupload-desc-here": "ꯃꯁꯤꯒꯤ ꯐꯥꯏꯜ ꯑꯁꯤ  $1 ꯗꯒꯤꯅꯤ ꯑꯃꯁꯨꯡ ꯑꯇꯩ ꯊꯧꯔꯥꯁꯁꯤꯡꯅꯥ ꯁꯤꯖꯤꯟꯅꯩ ꯫ ꯃꯁꯤꯗ ꯁꯟꯗꯣꯛꯅꯥ ꯇꯥꯛꯄ ꯑꯁꯤ  [$2 ꯐꯥꯏꯜ ꯁꯟꯗꯣꯛꯅꯥ ꯍꯥꯏꯕ ꯂꯃꯥꯏ] ꯃꯈꯥꯒꯤ ꯁꯤꯗ ꯎꯨꯠꯂꯦ ꯫",
        "booksources-search": "ꯊꯤꯕꯥ",
        "specialloguserlabel": "ꯄꯥꯡꯊꯣꯛꯂꯤꯕ ꯃꯤ",
        "log": "ꯆꯪꯕꯥ",
+       "logempty": "ꯃꯁꯤꯒ ꯆꯥꯟꯅꯕ ꯄꯣꯠꯂꯝꯁꯤꯡ ꯆꯪꯗꯦ",
        "allpages": "ꯂꯃꯥꯏꯁꯤꯡ ꯂꯣꯏꯅꯥ",
        "allarticles": "ꯂꯃꯥꯏꯁꯤꯡ ꯂꯣꯏꯅꯥ",
        "allpagessubmit": "ꯆꯠꯂꯨ",
        "allpages-hide-redirects": "ꯃꯥꯏꯀꯩ ꯄꯤꯔꯧꯄꯗꯨ ꯂꯣꯌꯂꯨ",
        "categories": "ꯃꯊꯪ ꯃꯅꯥꯎ ꯈꯥꯏꯗꯣꯛꯄꯥ",
+       "listgrouprights-members": "(ꯊꯧꯃꯤꯁꯤꯡ ꯄꯔꯤꯡ)",
        "emailuser": "ꯃꯁꯤ ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯁꯤ ꯏ-ꯃꯦꯜ ꯊꯥꯖꯤꯟꯂꯨ",
        "watchlist": "ꯌꯦꯡꯂꯤꯕ ꯄꯥꯥꯔꯦꯡ",
        "mywatchlist": "ꯌꯦꯡꯅꯕ ꯄꯔꯤꯡ",
        "namespace": "ꯃꯥꯃꯤꯡꯒꯤ ꯃꯐꯝ:",
        "invert": "ꯈꯟꯂꯤꯕꯗꯨ ꯃꯀꯣꯛꯇꯒꯤ ꯂꯥꯛꯍꯟꯕ",
        "tooltip-invert": "Akhannaba maming gi manungda page tungi ahongba lotnaba oopu du yeng ngoo",
-       "namespace_association": "Maming eefam ga marileinaba",
+       "namespace_association": "ꯃꯃꯤꯡ ꯏꯐꯝꯒ ꯃꯔꯤꯂꯩꯅꯕ",
        "tooltip-namespace_association": "Oopu du yengoo maming eefam gi hiramga mari leinaba khangatlaba maming eefam amadi wa ngangfam manung channaba",
        "blanknamespace": "(ꯃꯔꯨꯑꯣꯏꯕ)",
        "contributions": "{{GENDER:$1|ꯁꯤꯖꯤꯟꯅꯔꯤꯕ}} ꯈꯣꯝꯒꯠꯂꯛꯄꯁꯤꯡ",
        "tooltip-t-recentchangeslinked": "ꯃꯁꯤꯒꯤ ꯂꯃꯥꯏꯁꯤꯒꯥ ꯃꯔꯤ ꯂꯩꯅꯕꯥ ꯍꯧꯖꯤꯛꯀꯤ ꯑꯍꯣꯡꯕꯥ ꯂꯥꯃꯥꯏꯁꯤꯡ",
        "tooltip-feed-atom": "ꯂꯃꯥꯏꯁꯤꯒꯤ ꯃꯁꯥ ꯃꯇꯣꯝꯇꯥ ꯌꯣꯛꯈꯠꯂꯛꯄꯥ",
        "tooltip-t-contributions": " {{GENDER:$1|ꯃꯁꯤꯒꯤ ꯁꯤꯖꯤꯟꯅꯔꯤꯕ}} ꯑꯁꯤ ꯅꯥ ꯈꯣꯝꯖꯤꯟꯂꯛꯂꯤꯕꯥ ꯄꯥꯔꯦꯡ ꯱",
+       "tooltip-t-emailuser": "ꯏꯃꯦꯜ ꯱ ꯊꯥꯎ {{GENDER:$1|ꯃꯁꯤꯒꯤ ꯁꯤꯖꯤꯟꯔꯤꯕ}}ꯁꯤꯗ",
        "tooltip-t-upload": "ꯐꯥꯏꯜꯁꯤꯡ ꯊꯥꯒꯠꯂꯨ",
        "tooltip-t-specialpages": "ꯑꯈꯟꯅꯕ ꯂꯥꯃꯥꯏꯁꯤꯡꯒꯤ ꯄꯥꯔꯦꯡ ꯱",
        "tooltip-t-print": "ꯅꯝꯕ ꯌꯥꯕ ꯃꯑꯣꯡꯒꯤ ꯂꯃꯥꯏ",
-       "tooltip-t-permalink": "Amuk han na yengba lamaisigi Lengdaba Samnafam",
+       "tooltip-t-permalink": "ꯃꯃꯨꯛ ꯍꯟꯅ ꯌꯦꯡꯕ ꯂꯃꯥꯏꯒꯤ ꯂꯦꯡꯗꯕ ꯁꯝꯅꯐꯝ",
        "tooltip-ca-nstab-main": "ꯂꯃꯥꯏꯁꯤꯒꯤ ꯑꯌꯥꯎꯕꯁꯤꯡꯗꯨ ꯎꯨꯇꯂꯨ",
        "tooltip-ca-nstab-user": "ꯁꯤꯖꯤꯟꯅꯔꯤꯕꯥ ꯂꯥꯃꯥꯏꯁꯤ ꯌꯦꯡꯕꯥ",
        "tooltip-ca-nstab-special": "ꯃꯁꯤ ꯑꯈꯟꯅꯕꯥ ꯂꯃꯥꯏꯅꯤ, ꯁꯦꯝꯒꯠꯄꯥ ꯌꯥꯔꯣꯏ",
        "tooltip-ca-nstab-mediawiki": "ꯊꯧꯁꯤꯜꯒꯤ ꯑꯣꯏꯕ ꯄꯥꯎꯖꯦꯜꯗꯨ ꯎꯨꯠꯂꯨ",
        "tooltip-ca-nstab-template": "ꯇꯦꯝꯄꯂꯦꯠ ꯇꯨ ꯎꯨꯠꯂꯨ",
        "tooltip-ca-nstab-category": "ꯃꯆꯥꯈꯥꯏꯕ ꯂꯃꯥꯏꯗꯨ ꯎꯨꯠꯂꯨ",
+       "tooltip-minoredit": "ꯃꯁꯤꯗꯤ ꯑꯄꯤꯛꯄ ꯁꯦꯝꯒꯠꯄꯅꯤ",
        "tooltip-save": "ꯅꯪꯒꯤ ꯑꯍꯣꯡꯕꯗꯨ ꯇꯨꯡꯁꯤꯟꯂꯨ",
        "tooltip-preview": "ꯅꯪꯒꯤ ꯑꯍꯣꯡꯕꯗꯨ ꯑꯃꯨꯛ ꯍꯟꯅꯥ ꯎꯠꯂꯨ. ꯆꯥꯟꯕꯤꯗꯨꯅꯥ ꯃꯁꯤ ꯍꯥꯟꯅꯥ ꯁꯤꯖꯤꯅꯧ ꯇꯪꯨꯁꯤꯟꯗ꯭ꯔꯤꯉꯧꯗꯥ ꯫",
        "tooltip-diff": "ꯅꯪꯅꯥ ꯏꯔꯤꯕꯥ ꯄꯥꯔꯦꯡꯗꯨꯗꯥ ꯑꯍꯣꯡꯕꯥ ꯎꯠꯂꯨ",
        "pageinfo-lasttime": "ꯅꯧꯔꯤꯕ ꯁꯦꯝꯒꯠꯄꯒꯤ ꯆꯩꯆꯠ",
        "pageinfo-edits": "ꯑꯄꯨꯟꯕ ꯁꯦꯝꯒꯠꯄꯒꯤ ꯃꯁꯤꯡ",
        "pageinfo-authors": "ꯑꯄꯨꯟꯕ ꯑꯈꯟꯅꯕ ꯑꯌꯤꯕꯁꯤꯡꯒꯤ ꯃꯁꯤꯡ",
+       "pageinfo-recent-edits": "ꯀꯨꯏꯗꯔꯤꯕ ꯁꯦꯝꯒꯠꯄ ꯃꯁꯤꯡ($1 ꯐꯥꯎ ꯃꯅꯨꯡꯗ)",
        "pageinfo-magic-words": "ꯃꯦꯖꯤꯛ {{PLURAL:$1|ꯋꯥꯍꯩ|ꯋꯥꯍꯩꯁꯤꯡ}} ($1)",
        "pageinfo-hidden-categories": "ꯂꯣꯠꯍꯟꯕ {{PLURAL:$1|category|ꯃꯆꯥꯛꯈꯥꯏꯕ}} ($1)",
        "pageinfo-templates": "ꯇ꯭ꯔꯥꯟꯁꯀꯂꯨꯗꯦꯗ {{PLURAL:$1|ꯇꯦꯝꯄꯂꯦꯠ|ꯇꯦꯝꯄꯂꯦꯠꯁꯤꯡ}} ($1)",
index b6fa2af..fef0de8 100644 (file)
        "blocklist-timestamp": "အချိန်တံဆိပ်",
        "blocklist-target": "ပစ်မှတ်",
        "blocklist-expiry": "သက်တမ်းကုန်လွန်မည်",
-       "blocklist-by": "á\80\95á\80\90á\80ºá\80\95á\80\84á\80ºá\80\91á\80¬á\80¸á\80\9eá\80\8aá\80·á\80º á\80¡á\80\80á\80ºá\80\92á\80\99á\80­á\80\94á\80º",
+       "blocklist-by": "á\80\95á\80­á\80\90á\80ºá\80\95á\80\84á\80ºá\80\91á\80¬á\80¸á\80\9eá\80\8aá\80·á\80º á\80\85á\80®á\80\99á\80¶á\80\81á\80\94á\80·á\80ºá\80\81á\80½á\80²á\80\9eá\80°",
        "blocklist-params": "ပိတ်ပင်မှု ပါရာမီတာများ",
        "blocklist-reason": "အကြောင်းပြချက်",
        "ipblocklist-submit": "ရှာဖွေရန်",
        "tag-mw-undo": "နောက်ပြန် ပြန်ပြင်ခြင်း",
        "tags-title": "အမည်တွဲများ",
        "tags-tag": "အမည်တွဲ အမည်",
+       "tags-display-header": "ပြောင်းလဲချက် စာရင်းများပေါ်တွင် ပေါ်ထင်မှု",
        "tags-description-header": "ဆိုလိုရင်းအဓိပ္ပာယ် အပြည့်အစုံ",
        "tags-source-header": "ရင်းမြစ်",
+       "tags-active-header": "သက်ဝင်?",
+       "tags-hitcount-header": "အမည်တွဲထားသော ပြောင်းလဲမှုများ",
        "tags-actions-header": "ဆောင်ရွက်ချက်များ",
        "tags-active-yes": "မှန်",
        "tags-active-no": "မလုပ်ပါ",
index dd6aa2e..3365b11 100644 (file)
        "redirectedfrom": "(Redirect 'a $1)",
        "redirectpagesub": "Paggena 'e redirect",
        "redirectto": "Reindirizza a:",
-       "lastmodifiedat": "Sta paggena fuje cagnàta ll'urdema vota 'o $1, 'e $2.",
+       "lastmodifiedat": "Sta paggena venette cagnàta ll'urdema vota 'o $1, 'e $2.",
        "viewcount": "Chesta paggena è stata liggiùta {{PLURAL:$1|una vòta|$1 vòte}}.",
        "protectedpage": "Paggena prutetta",
        "jumpto": "Vaje a:",
        "externaldberror": "Ce sta n'errore ch' 'e server d'autenticazione esterno, o pure nun v'è permesso accedere all'aghiurnamento d' 'o cunto sterno vuosto.",
        "login": "Tràse",
        "login-security": "Cunferma l'identità",
-       "nav-login-createaccount": "Trasite o criate n'acciesso nuovo",
+       "nav-login-createaccount": "Trasite o criate n'acciesso novo",
        "logout": "Jèsce",
        "userlogout": "Jèsce",
        "notloggedin": "Acciesso nun affettuato",
-       "userlogin-noaccount": "Nun tenite perzine n'acciesso?",
+       "userlogin-noaccount": "Perzine nun tenite n'acciesso?",
        "userlogin-joinproject": "Facite 'o riggistro ncopp'a {{SITENAME}}",
        "createaccount": "Crèa nu cunto nuovo",
        "userlogin-resetpassword-link": "Te sì scurdat' 'a password?",
        "newarticle": "(Nuovo)",
        "newarticletext": "Site ghiuto/a addò nu link 'e na paggena ca nun esiste ancora.\nPe crià sta paggena, accummenciate a scrivere dint'<nowiki/>'a cascia ccà abbascio (vedite 'a [$1 paggena d'aiuto] pe vedè cchiù 'nfurmazziune).\nSi site venuto/a ccà pe sbaglio, vedite 'e sprémmere 'o buttòne '''Arreto''' d'<nowiki/>o navigatóre.",
        "anontalkpagetext": "----\n''Chest'è 'a paggena 'e discussione 'e n'utente anonimo ca ancora nun s'è fatt' n'utenza o ca nun 'a sta ausanno.''\n\nPe' l'identificà avite 'e truvà 'o nummero d' 'o ndirizzo IP d' 'o sujo. L'indirizze IP se ponno spartì però sempe ausanno cunte differente.\n\nSi site n'utente anonimo e penzate ca 'e cummente ccà dint'a sta paggena nun parlano 'e vuje, allora [[Special:CreateAccount|criate n'utenza nnova]] o [[Special:UserLogin|trasite cu chella ca tenite già]] pe' nun sta' mmescato mmiez'a l'ati utente anonime n futuro.",
-       "noarticletext": "Mo' mo' 'a paggena richiesta è abbacante. Se pò [[Special:Search/{{PAGENAME}}|ascià stu titolo]] dint'a l'ati paggene d' 'o sito, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ascià dint'e riggistre azzeccate] o pure [{{fullurl:{{FULLPAGENAME}}|action=edit}} crià 'a paggena mo']</span>.",
-       "noarticletext-nopermission": "Mo' mo' 'a paggena richiesta è abbacante. Se pò [[Special:Search/{{PAGENAME}}|ascià stu titolo]] dint'a l'ati paggene d' 'o sito, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ascià dint'e riggistre azzeccate]</span>, però nun tenite 'o permesso 'a crià sta paggena.",
+       "noarticletext": "Mo mmo 'a paggena richiesta è abbacante. Può [[Special:Search/{{PAGENAME}}|ascià stu titolo]] dint' 'a ll'ati paggene d' 'o sito, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ascià dint'e riggistre azzeccate] o pure [{{fullurl:{{FULLPAGENAME}}|action=edit}} crià 'a paggena 'a via 'e subbeto]</span>.",
+       "noarticletext-nopermission": "Mo mmo 'a paggena richiesta è abbacante. Se pò [[Special:Search/{{PAGENAME}}|ascià stu titolo]] dint' 'a ll'ati paggene d' 'o sito, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ascià dint'e riggistre azzeccate]</span>, però nun tenite 'o permesso 'e crià sta paggena.",
        "missing-revision": "'A verziona #$1 d' 'a paggena \"{{FULLPAGENAME}}\" nun esiste.\n\nChest'è causato quanno se và dint'a nu link a na paggena ch'è stata scancellata.\n'E dettaglie se ponno truvà dint'a [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} 'o riggistro 'e scancellamiente].",
        "userpage-userdoesnotexist": "'O cunto utente \"<nowiki>$1</nowiki>\" nun è riggistrato. Cuntrolla ca si buò overo crià o cagnà sta paggena.",
        "userpage-userdoesnotexist-view": "'O cunto utente \"$1\" nun è riggistrato.",
        "blocked-notice-logextract": "St'utente è bloccato mò.\nL'urdemo elemento d' 'o riggistro 'e blocche è ripurtato ccà abbascio p'avé nu riferimento:",
-       "clearyourcache": "<strong>Nota:</strong> aroppo sarvate putisse necessità 'e pulezzà 'a caché d' 'o navigatóre pe' vedé 'e cagnamiente. \n*<strong>Firefox / Safari</strong>: sprémme 'o buttóne maiuscole e ffà clic ncopp'a ''Recarreca'', o pure spremme ''Ctrl-F5'' o ''Ctrl-R'' (''⌘-R'' ncopp'a Mac)\n*<strong>Google Chrome''': spremme ''Ctrl-Shift-R'' (''⌘-Shift-R'' ncopp'a nu Mac)\n*<strong>Internet Explorer</strong>: spremme 'o buttóne ''Ctrl'' pe' tramente ca faie click ncopp'a ''Refresh'', o pure spremmere ''Ctrl-F5''\n* <strong>Opera:</strong> Vaje addò 'o <em>Menu → Mpustaziune</em> (<em>Opera → Mpustaziune</em> ncopp' 'o Mac) e po' ncopp'a <em>Privacy & sicurezza → Pulezza date d' 'o browser → Immaggene e file d' 'a cache</em>.",
+       "clearyourcache": "<strong>Notarella:</strong> aroppo sarvate putisse necessità 'e pulezzà 'a caché d' 'o navigatóre pe vedé 'e cagnamienti. \n*<strong>Firefox / Safari</strong>: sprémme 'o buttóne maiuscole e ffà clic ncopp'a ''Recarreca'', o pure spremme ''Ctrl-F5'' o ''Ctrl-R'' (''⌘-R'' ncopp'a Mac)\n*<strong>Google Chrome''': spremme ''Ctrl-Shift-R'' (''⌘-Shift-R'' ncopp'a nu Mac)\n*<strong>Internet Explorer</strong>: spremme 'o buttóne ''Ctrl'' pe' tramente ca faie click ncopp'a ''Refresh'', o pure spremmere ''Ctrl-F5''\n* <strong>Opera:</strong> Vaje addò 'o <em>Menu → Mpustaziune</em> (<em>Opera → Mpustaziune</em> ncopp' 'o Mac) e po' ncopp'a <em>Privacy & sicurezza → Pulezza date d' 'o browser → Immaggene e file d' 'a cache</em>.",
        "usercssyoucanpreview": "'''Cunziglio:''' spremme 'o buttone 'Vide anteprimma' pe' pruvà 'o CSS nuovo apprimma d' 'o sarvà.",
        "userjsonyoucanpreview": "<strong>Cunziglio:</strong> premme 'o buttone \"{{int:showpreview}}\" pe' pruvà 'o JSON nuovo apprimma d' 'o sarvà.",
        "userjsyoucanpreview": "'''Cunziglio:''' spremme 'o buttone 'Vide anteprimma' pe' pruvà 'o JavaScript nuovo apprimma d' 'o sarvà.",
        "protect-existing-expiry-infinity": "Tiempo d'ammaturamiento: infinito",
        "protect-otherreason": "Ati/cchiù ragiune:",
        "protect-otherreason-op": "Ati ragiune",
-       "protect-dropdown": "*Mutive 'e prutezione comune\n** Vandalisme eccessive\n** Spam eccessivo\n** 'Uerre 'e cagnamiente controproducente\n** Paggena cu troppo traffeco",
+       "protect-dropdown": "*Mutive 'e prutezione comune\n** Vandalisme eccessive\n** Spam eccessivo\n** 'Uerra 'e cagnamienti controproducente\n** Paggena cu assaje traffeco\n** Paggena 'e sistema ausata assai",
        "protect-edit-reasonlist": "Càgna 'e mutive 'e prutezione",
        "protect-expiry-options": "1 ore:1 hour,1 juorno:1 day,1 semmana:1 week,2 semmane:2 weeks,1 mese:1 month,3 mise:3 months,6 mise:6 months,1 anno:1 year,infinito:infinite",
        "restriction-type": "Permesse:",
        "specialpages-note-restricted": "* Paggene speciale normale.\n* <span class=\"mw-specialpagerestricted\">Paggene speciale ch' 'e restriziune.</span>",
        "specialpages-group-maintenance": "Report 'e manutenzione",
        "specialpages-group-other": "Ati paggene speciale",
-       "specialpages-group-login": "Trasite o criate n'acciesso nuovo",
+       "specialpages-group-login": "Trasite o criate n'acciesso novo",
        "specialpages-group-changes": "Urdeme cagnamiénte e riggistre",
        "specialpages-group-media": "Riepileghe 'e media e carreche",
        "specialpages-group-users": "Utente e deritte",
index 7ccdd86..88c7bc7 100644 (file)
        "tog-useeditwarning": "Si ifra dersom jeg forlater en side uten å lagre den.",
        "tog-prefershttps": "Bruk alltid en trygg forbindelse når du er innlogget",
        "tog-showrollbackconfirmation": "Be om bekreftelse når man klikker på en tilbakestillingslenke",
+       "tog-requireemail": "Krev epost for tilbakestilling av passord",
        "underline-always": "Alltid",
        "underline-never": "Aldri",
        "underline-default": "Drakta eller nettleserens standardinnstillinger",
        "undo-norev": "Redigeringen kunne ikke fjernes fordi den ikke eksisterer eller ble slettet",
        "undo-nochange": "Det ser ut til at redigeringen allerede er tilbakestilt.",
        "undo-summary": "Fjerner revisjon $1 av [[Special:Contributions/$2|$2]] ([[User talk:$2|diskusjon]])",
+       "undo-summary-anon": "Fjerner revisjon $1 av [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Fjern revisjon $1 av en skjult bruker",
        "cantcreateaccount-text": "Kontooppretting fra denne IP-adressen ('''$1''') har blitt blokkert av [[User:$3|$3]].\n\nGrunnen som ble oppgitt av $3 er ''$2''",
        "cantcreateaccount-range-text": "Opprettelsen av en brukerkonto fra IP-adresser i intervallet <strong>$1</strong>, som inneholder din IP-adresse (<strong>$4</strong>), er blitt blokkert av [[User:$3|$3]].\n\nÅrsaken angitt av $3 er <em>$2</em>",
        "prefs-help-email": "Å angi e-postadresse er valgfritt, men er nødvendig for å få tilsendt nytt passord om du skulle glemme det gamle.",
        "prefs-help-email-others": "Du kan også velge å la andre brukere kontakte deg via brukersiden din uten å røpe identiteten din.",
        "prefs-help-email-required": "E-postadresse er påkrevd.",
+       "prefs-help-requireemail": "Hvis denne er valgt vil vi kunne sende eposter om tilbakestilling av passord dersom den som ber om det oppgir både brukernavn og epostadresse for kontoen.",
        "prefs-info": "Grunnleggende informasjon",
        "prefs-i18n": "Internasjonalisering",
        "prefs-signature": "Signatur",
        "alreadyrolled": "Kan ikke fjerne den siste redigeringen på [[$1]] av [[User:$2|$2]] ([[User talk:$2|diskusjon]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); en annen har allerede redigert siden eller fjernet redigeringen.\n\nDen siste redigeringen ble foretatt av [[User:$3|$3]] ([[User talk:$3|diskusjon]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Redigeringskommentaren var: <em>$1</em>",
        "revertpage": "Tilbakestilte endringer av [[Special:Contributions/$2|$2]] ([[User talk:$2|brukerdiskusjon]]) til siste versjon av [[User:$1|$1]]",
+       "revertpage-anon": "Tilbakestilte endringer av [[Special:Contributions/$2|$2]] til siste versjon av [[User:$1|$1]]",
        "revertpage-nouser": "Tilbakestilt endringer av skjult bruker til siste versjon av\n{{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Tilbakestilte endringer av {{GENDER:$3|$1}}; endret til siste versjon av {{GENDER:$4|$2}}.",
        "sessionfailure-title": "Sesjonsfeil",
index dec927a..626fbc8 100644 (file)
                        "PiefPafPier"
                ]
        },
-       "tog-underline": "Verwiezingen onderstrepen",
-       "tog-hideminor": "Kleine wiezigingen verbargen in \"Leste wiezigingen\"",
-       "tog-hidepatrolled": "Wiezigingen die emarkeerd bin verbargen in \"Leste wiezigingen\"",
-       "tog-newpageshidepatrolled": "Ziejen die emarkeerd bin, verbargen in de lieste mit nieje artikels",
-       "tog-extendwatchlist": "Volglieste uutbreien, zodat alle wiezigingen zichtbaor bin, en niet allinnig de leste wieziging",
-       "tog-usenewrc": "Groepeer wiezigingen per zied in \"Leste wiezigingen\" en \"Mien volglieste\"",
-       "tog-numberheadings": "Koppen vanzelf nummeren",
-       "tog-editondblclick": "Mit dubbelklik bewarken",
-       "tog-editsectiononrightclick": "Bewarken van deelziejen meugelik maken mit n rechtermuusklik op n tussenkop",
-       "tog-watchcreations": "Spul wa'k anmake op mien volglieste zetten",
-       "tog-watchdefault": "Spul wa'k bewarke op mien volglieste zetten",
-       "tog-watchmoves": "Spul wa'k herneume op mien volglieste zetten",
-       "tog-watchdeletion": "Spul wa'k vortdo op mien volglieste zetten",
-       "tog-watchrollback": "Ziejen waorvan ik bewarkingen weerummedreid hebbe automaties volgen",
-       "tog-minordefault": "Markeer alle veraanderingen as 'kleine wieziging'",
-       "tog-previewontop": "De naokiekzied boven t bewarkingsveld zetten",
-       "tog-previewonfirst": "Naokieken bie eerste wieziging",
-       "tog-enotifwatchlistpages": "Stuur mien n berichjen over zied- of bestaandswiezigingen uut mien volglieste.",
-       "tog-enotifusertalkpages": "Stuur mien n berichjen as mien overlegzied ewiezigd is.",
-       "tog-enotifminoredits": "Stuur mien oek n berichjen bie kleine bewarkingen van ziejen en bestaanden",
-       "tog-enotifrevealaddr": "Mien netpostadres laoten zien in netposttiejigen",
-       "tog-shownumberswatching": "t Antal gebrukers bekieken die disse zied volgt",
-       "tog-oldsig": "Bestaonde haandtekening:",
-       "tog-fancysig": "Ondertekening zien as wikitekste (zonder automatiese verwiezing)",
-       "tog-uselivepreview": "Gebruuk \"rechtstreeks naokieken\"",
-       "tog-forceeditsummary": "Geef n melding bie n lege samenvatting",
-       "tog-watchlisthideown": "Verbarg mien eigen bewarkingen",
-       "tog-watchlisthidebots": "Verbarg botgebrukers",
-       "tog-watchlisthideminor": "Verbarg kleine wiezigingen in mien volglieste",
-       "tog-watchlisthideliu": "Bewarkingen van an-emelde gebrukers op mien volglieste verbargen",
-       "tog-watchlisthideanons": "Bewarkingen van anonieme gebrukers op mien volglieste verbargen",
-       "tog-watchlisthidepatrolled": "Wiezigingen die emarkeerd bin op volglieste verbargen",
-       "tog-ccmeonemails": "Stuur mien kopieën van berichten an aandere gebrukers",
-       "tog-diffonly": "Laot de inhoud van ziejen niet onder de an-egeven wiezigingen zien.",
-       "tog-showhiddencats": "Laot verbörgen kategorieën zien",
-       "tog-norollbackdiff": "Wiezigingen vortlaoten nao t weerummedreien",
-       "tog-useeditwarning": "Waorschuw mien a'k n bewörken zied aof wil sluten die nog niet op-esleugen is",
-       "tog-prefershttps": "Altied n beveiligde verbiending gebruken a'j an-emeld bin",
-       "underline-always": "Altied",
+       "tog-underline": "Verwysingen understreapen",
+       "tog-hideminor": "Kleine wysigingen verbargen in \"Lätste wysigingen\"",
+       "tog-hidepatrolled": "Wysigingen dee markeerd binnet verbargen in \"Lätste wysigingen\"",
+       "tog-newpageshidepatrolled": "Syden dee markeerd binnet, verbargen in de lyste mid nye artikels",
+       "tog-extendwatchlist": "Volglyste uutbreiden, sodat alle wysigingen sichtbår binnet, en neet allinnig de lätste wysigingen",
+       "tog-usenewrc": "Gruppeer wysigingen per syde in \"Lätste wysigingen\" en \"Myn volglyste\"",
+       "tog-numberheadings": "Upskrivten vanselv nummeren",
+       "tog-editondblclick": "Mid dubbelklik bewarken",
+       "tog-editsectiononrightclick": "Bewarken van deylsyden möägelik maken mid een rechtermuusklik up een tüskenupskrivt",
+       "tog-watchcreations": "Spül wat ik anmake up myn volglyste setten",
+       "tog-watchdefault": "Spül wat ik bewarke up myn volglyste setten",
+       "tog-watchmoves": "Spül wat ik hernöme up myn volglyste setten",
+       "tog-watchdeletion": "Spül wat ik vordsmyte up myn volglyste setten",
+       "tog-watchrollback": "Syden wårvan ik bewarkingen weaderümmedraid hebbe automatisk volgen",
+       "tog-minordefault": "Markeer alle veranderingen as 'kleine wysiging'",
+       "tog-previewontop": "De nåkyksyde boaven et bewarkingsveld setten",
+       "tog-previewonfirst": "Nåkyken by eyrste wysiging",
+       "tog-enotifwatchlistpages": "Stüür my een bericht oaver syd- of bestandswysigingen uut myn volglyste.",
+       "tog-enotifusertalkpages": "Stüür my een bericht as myn oaverlegsyde wysigd is.",
+       "tog-enotifminoredits": "Stüür my ouk een bericht by kleine bewarkingen van syden en bestanden",
+       "tog-enotifrevealaddr": "Myn e-postadres låten seen in e-postberichten",
+       "tog-shownumberswatching": "Et antal brukers bekyken dee disse syde volgt",
+       "tog-oldsig": "Bestånde handteykening:",
+       "tog-fancysig": "Underteykening seen as wikitekst (sunder automatiske verwysing)",
+       "tog-uselivepreview": "Nåkyksyde låten seen sunder eyrst te herladen",
+       "tog-forceeditsummary": "Geav een melding by een leadige samenvatting",
+       "tog-watchlisthideown": "Verbarg myn eigen bewarkingen",
+       "tog-watchlisthidebots": "Verbarg botbrukers",
+       "tog-watchlisthideminor": "Verbarg kleine wysigingen in myn volglyste",
+       "tog-watchlisthideliu": "Bewarkingen van anmeldede brukers up myn volglyste verbargen",
+       "tog-watchlisthideanons": "Bewarkingen van anonyme brukers up myn volglyste verbargen",
+       "tog-watchlisthidepatrolled": "Wysigingen dee markeerd binnet up volglyste verbargen",
+       "tog-ccmeonemails": "Stüür my kopien van berichten an andere brukers",
+       "tog-diffonly": "Under wysigingen neet de syde-inhold låten seen.",
+       "tog-showhiddencats": "Låt verbörgen kategoryen seen",
+       "tog-norollbackdiff": "Wysigingen vordlåten nå et weaderümmedraien",
+       "tog-useeditwarning": "Wårschüw my as ik een bewarkede syde afsluten wil dee noch neet seakerd is",
+       "tog-prefershttps": "Altyd een beveiligde verbinding bruken as jy anmelded binnet",
+       "underline-always": "Altyd",
        "underline-never": "Nooit",
-       "underline-default": "Standard in joew vormgeving of webkieker",
-       "editfont-style": "Lettertype veur de tekste t bewarkingsveld:",
-       "editfont-monospace": "Lettertype waorvan t tekenbreedte vaste steet",
+       "underline-default": "Standard in juw formgeaving of webkyker",
+       "editfont-style": "Lettertype vöär de tekst in et bewarkingsveld:",
+       "editfont-monospace": "Lettertype wårvan de teykenbreydte vast steyt",
        "editfont-sansserif": "Sans-seriflettertype",
        "editfont-serif": "Seriflettertype",
        "sunday": "sündag",
@@ -94,9 +94,9 @@
        "october": "oktober",
        "november": "november",
        "december": "december",
-       "january-gen": "jannewaori",
+       "january-gen": "janri",
        "february-gen": "februåri",
-       "march-gen": "meert",
+       "march-gen": "määrt",
        "april-gen": "april",
        "may-gen": "mei",
        "june-gen": "juni",
        "september-gen": "september",
        "october-gen": "oktober",
        "november-gen": "november",
-       "december-gen": "desember",
+       "december-gen": "december",
        "jan": "jan",
        "feb": "feb",
        "mar": "mrt",
        "oct": "okt",
        "nov": "nov",
        "dec": "dec",
-       "january-date": "$1 jannewaori",
-       "february-date": "$1 febrewaori",
-       "march-date": "$1 meert",
+       "january-date": "$1 janri",
+       "february-date": "$1 febrri",
+       "march-date": "$1 määrt",
        "april-date": "$1 april",
        "may-date": "$1 mei",
        "june-date": "$1 juni",
        "september-date": "$1 september",
        "october-date": "$1 oktober",
        "november-date": "$1 november",
-       "december-date": "$1 desember",
+       "december-date": "$1 december",
        "pagecategories": "{{PLURAL:$1|Kategory|Kategoryen}}",
-       "category_header": "Artikels in kategorie $1",
-       "subcategories": "Subkategorieën",
-       "category-media-header": "Media in kategorie \"$1\"",
-       "category-empty": "''In disse kategoria staon op t moment nog gien artikels of media.''",
+       "category_header": "Artikels in kategory $1",
+       "subcategories": "Subkategoryen",
+       "category-media-header": "Media in kategory \"$1\"",
+       "category-empty": "<em>In disse kategory stån up et moment noch geen syden of media.</em>",
        "hidden-categories": "Verbörgen {{PLURAL:$1|kategory|kategoryen}}",
-       "hidden-category-category": "Verbörgen kategorieën",
+       "hidden-category-category": "Verbörgen kategoryen",
        "category-subcat-count": "{{PLURAL:$2|Disse kategory hevt de volgende subkategory.|Disse kategory hevt de volgende {{PLURAL:$1|subkategory|$1 subkategoryen}}, van in totaal $2.}}",
-       "category-subcat-count-limited": "Disse kategorie hef de volgende {{PLURAL:$1|subkategorie|$1 subkategorieën}}.",
+       "category-subcat-count-limited": "Disse kategory hevt de volgende {{PLURAL:$1|subkategory|$1 subkategoryen}}.",
        "category-article-count": "{{PLURAL:$2|In disse kategory steyt allinnig de volgende syde.|De volgende {{PLURAL:$1|syde steyt|$1 syden stån}} in disse kategory, van in totaal $2.}}",
-       "category-article-count-limited": "In disse kategorie {{PLURAL:$1|steet de volgende zied|staon de volgende $1 ziejen}}.",
-       "category-file-count": "In disse kategorie {{PLURAL:$2|steet t volgende bestaand|staon de volgende $1 bestaanden, van in totaal $2}}.",
-       "category-file-count-limited": "In disse kategorie {{PLURAL:$1|steet t volgende bestaand|staon de volgende $1 bestaanden}}.",
+       "category-article-count-limited": "In disse kategory {{PLURAL:$1|steyt de volgende syde|stån de volgende $1 syden}}.",
+       "category-file-count": "In disse kategory {{PLURAL:$2|steyt et volgende bestand|stån de volgende $1 bestanden, van in totaal $2}}.",
+       "category-file-count-limited": "In disse kategory {{PLURAL:$1|steyt et volgende bestand|stån de volgende $1 bestanden}}.",
        "listingcontinuesabbrev": "(vervolg)",
-       "index-category": "Te indexeren ziejen",
+       "index-category": "Te indekseren syden",
        "noindex-category": "Syden dee neet indexeerd binnen",
-       "broken-file-category": "Ziejen mit verkeerde bestaandsverwiezingen",
-       "about": "Informasie",
+       "broken-file-category": "Syden mid verkeyrde bestandsverwysingen",
+       "about": "Informaty",
        "article": "Artikel",
-       "newwindow": "(niej vienster)",
+       "newwindow": "(ny vinster)",
        "cancel": "Afbreaken",
-       "moredotdotdot": "Meer...",
-       "morenotlisted": "Disse lieste is niet kompleet...",
-       "mypage": "Gebrukerszied",
+       "moredotdotdot": "Meyr...",
+       "morenotlisted": "Disse lyste is möägelik neet kompleet.",
+       "mypage": "Brukerssyde",
        "mytalk": "Myn oaverleg",
        "anontalk": "Oaverleg",
        "navigation": "Navigaty",
        "and": "&#32;en",
-       "faq": "Vragen die vake esteld wörden",
-       "actions": "Haandeling",
+       "faq": "Vake stelde vrågen",
+       "actions": "Handelingen",
        "namespaces": "Naamruumdes",
        "variants": "Varianten",
-       "navigation-heading": "Navigatymenu",
+       "navigation-heading": "Navigatymenü",
        "errorpagetitle": "Foutmelding",
-       "returnto": "Weerumme naor $1.",
+       "returnto": "Weaderümme nå $1.",
        "tagline": "Van {{SITENAME}}",
        "help": "Hülpe",
        "search": "Söken",
        "updatedmarker": "bie-ewörken sinds mien leste bezeuk",
        "printableversion": "Afdrükbåre versy",
        "permalink": "Vaste verwysing",
-       "print": "Aofdrokken",
+       "print": "Afdrükken",
        "view": "Leasen",
-       "view-foreign": "Bekieken op $1",
+       "view-foreign": "Bekyken up $1",
        "edit": "Bewarken",
        "edit-local": "Lokale beschrieving bewarken",
        "create": "Anmaken",
-       "create-local": "Lokale beschrieving derbie doon",
-       "delete": "Vortdoon",
-       "undelete_short": "$1 {{PLURAL:$1|versie|versies}} weerummeplaotsen",
-       "viewdeleted_short": "{{PLURAL:$1|Eén versie die vortedaon is|$1 versies die vortedaon bin}} bekieken",
+       "create-local": "Lokale beskryving tovogen",
+       "delete": "Vordsmyten",
+       "undelete_short": "$1 {{PLURAL:$1|versy|versys}} weaderümmeplaatsen",
+       "viewdeleted_short": "{{PLURAL:$1|Eyn versy dee vordsmeaten is|$1 versys dee vortsmeaten binnet}} bekyken",
        "protect": "Beveiligen",
-       "protect_change": "wiezigen",
+       "protect_change": "wysigen",
        "unprotect": "Beveiliging wysigen",
-       "newpage": "Nieje zied",
+       "newpage": "Nye syde",
        "talkpagelinktext": "Oaverleg",
        "specialpage": "Speciale syde",
        "personaltools": "Persoonlike instellingen",
        "talk": "Oaverleg",
        "views": "Weadergåven",
-       "toolbox": "Hülpmiddels",
-       "tool-link-userrights": "{{GENDER:$1|Gebrukersgruppen}} wysigen",
-       "tool-link-emailuser": "Disse {{GENDER:$1|gebruker}} een bericht stüren",
-       "imagepage": "Bestaandszied bekieken",
-       "mediawikipage": "Tiejige bekieken",
-       "templatepage": "Mal bekieken",
-       "viewhelppage": "Hulpzied bekieken",
-       "categorypage": "Kategoriezied bekieken",
-       "viewtalkpage": "Bekiek overlegzied",
+       "toolbox": "Warktügen",
+       "tool-link-userrights": "{{GENDER:$1|Brukersgruppen}} wysigen",
+       "tool-link-emailuser": "Disse {{GENDER:$1|bruker}} een bericht stüren",
+       "imagepage": "Bestandssyde bekyken",
+       "mediawikipage": "Berichtsyde bekyken",
+       "templatepage": "Mal bekyken",
+       "viewhelppage": "Hülpsyde bekyken",
+       "categorypage": "Kategorysyde bekyken",
+       "viewtalkpage": "Bekyk oaverlegsyde",
        "otherlanguages": "Andere språken",
        "redirectedfrom": "(döärstüürd vanaf \"$1\")",
-       "redirectpagesub": "Deurverwieszied",
-       "redirectto": "Deurverwiezen naor:",
+       "redirectpagesub": "Döärverwyssyde",
+       "redirectto": "Döärverwysen nå:",
        "lastmodifiedat": "Disse syde is et lätst wysigd up $1 üm $2.",
-       "viewcount": "Disse zied is $1 {{PLURAL:$1|keer|keer}} bekeken.",
-       "protectedpage": "Beveiligden zied",
+       "viewcount": "Disse syde is $1 {{PLURAL:$1|keyr}} bekeaken.",
+       "protectedpage": "Beveiligde syde",
        "jumpto": "Gå nå:",
        "jumptonavigation": "navigaty",
        "jumptosearch": "söök",
-       "view-pool-error": "De servers bin op heden overbelast.\nTe veule gebrukers proberen disse zied te bekieken.\nWacht effen veurda'j opniej toegang proberen te kriegen tot disse zied.\n\n$1",
-       "generic-pool-error": "De servers bin op heden overbelast.\nTe veule gebrukers proberen disse zied te bekieken.\nWacht effen veurda'j opniej toegang proberen te kriegen tot disse zied.",
-       "pool-timeout": "De maximumwachttied veur databankvergrendeling is verleupen.",
-       "pool-queuefull": "De wachtrie van de poel is vol",
-       "pool-errorunknown": "Onbekende fout",
-       "pool-servererror": "De dienst \"pool counter\" is niet beschikbaor ($1).",
+       "view-pool-error": "De servers binnet momenteel oaverbelasted.\nTe vöäle lüde proberet disse syde te bekyken.\nWacht evven vöärdat jy upny togang proberet te krygen tot disse syde.\n\n$1",
+       "generic-pool-error": "De servers binnet momenteel oaverbelasted.\nTe vöäle lüde proberet disse syde te bekyken.\nWacht evven vöärdat jy upny togang proberet te krygen tot disse syde.",
+       "pool-timeout": "De maksimumwachttyd vöär databankvergrendeling is verlöypen.",
+       "pool-queuefull": "De wachtryge van de pool is vul",
+       "pool-errorunknown": "Unbekende faut",
+       "pool-servererror": "De deenst \"pool counter\" is neet beskikbår ($1).",
        "aboutsite": "Oaver {{SITENAME}}",
        "aboutpage": "Project:Info",
        "copyright": "De inhoud is beschikbaor onder de $1 as der niks aanders an-egeven is.",
-       "copyrightpage": "{{ns:project}}:Auteursrechten",
+       "copyrightpage": "{{ns:project}}:Autöörsrechten",
        "currentevents": "In et nys",
        "currentevents-url": "Project:In et nys",
        "disclaimers": "Vöärbehold",
        "disclaimerpage": "Project:Vöärbehold",
-       "edithelp": "Hulpe mit bewarken",
-       "helppage-top-gethelp": "Hulpe",
+       "edithelp": "Hülpe mid bewarken",
+       "helppage-top-gethelp": "Hülpe",
        "mainpage": "Vöärblad",
        "mainpage-description": "Vöärblad",
        "policy-url": "Project:Beleid",
        "portal-url": "Project:Gemeynskapsportaal",
        "privacy": "Gegeavensbeleid",
        "privacypage": "Project:Gegeavensbeleid",
-       "badaccess": "Gien toestemming",
-       "badaccess-group0": "Je hebben gien toestemming um disse aksie uut te voeren.",
-       "badaccess-groups": "Disse aksie kan allinnig uutevoerd wörden deur gebrukers uut {{PLURAL:$2|de groep|één van de groepen}}: $1.",
-       "versionrequired": "Versie $1 van MediaWiki is neudig",
-       "versionrequiredtext": "Versie $1 van MediaWiki is neudig um disse zied te gebruken. Zie [[Special:Version|Versie]].",
-       "ok": "Best",
+       "badaccess": "Geen tostemming",
+       "badaccess-group0": "Jy hebbet geen tostemming üm disse akty uut te voren.",
+       "badaccess-groups": "Disse akty kan allinnig uutvoord wörden döär brukers uut {{PLURAL:$2|de grup|eyn van de gruppen}}: $1.",
+       "versionrequired": "Versy $1 van MediaWiki is nöydig",
+       "versionrequiredtext": "Versy $1 van MediaWiki is nöydig üm disse syde te bruken. See [[Special:Version|Versy]].",
+       "ok": "Okee",
        "retrievedfrom": "Van \"$1\"",
-       "youhavenewmessages": "Je hebben $1 ($2).",
-       "youhavenewmessagesfromusers": "Je hebben $1 van {{PLURAL:$3|n aandere gebruker|$3 gebrukers}} ($2).",
-       "youhavenewmessagesmanyusers": "Je hebben $1 van n bulte gebrukers ($2).",
-       "newmessageslinkplural": "{{PLURAL:$1|n niej bericht|999=nieje berichten}}",
-       "newmessagesdifflinkplural": "leste {{PLURAL:$1|wieziging|999=wiezigingen}}",
-       "youhavenewmessagesmulti": "Jy hebben nye berichten up $1",
+       "youhavenewmessages": "{{PLURAL:$3|Jy hebbet}} $1 ($2).",
+       "youhavenewmessagesfromusers": "{{PLURAL:$4|Jy hebbet}} $1 van {{PLURAL:$3|een andere bruker|$3 brukers}} ($2).",
+       "youhavenewmessagesmanyusers": "Jy hebbet $1 van een bült brukers ($2).",
+       "newmessageslinkplural": "{{PLURAL:$1|een ny bericht|999=nye berichten}}",
+       "newmessagesdifflinkplural": "läste {{PLURAL:$1|wysiging|999=wysigingen}}",
+       "youhavenewmessagesmulti": "Jy hebbet nye berichten up $1",
        "editsection": "bewark",
        "editold": "bewark",
-       "viewsourceold": "brontekste bekyken",
+       "viewsourceold": "brontekst bekyken",
        "editlink": "bewark",
        "viewsourcelink": "brontekst bekyken",
        "editsectionhint": "Bewarkingsveld: $1",
        "toc": "Inhold",
-       "showtoc": "Bekieken",
-       "hidetoc": "Verbarg",
+       "showtoc": "bekyken",
+       "hidetoc": "verbargen",
        "collapsible-collapse": "Inklappen",
        "collapsible-expand": "Uutklappen",
-       "confirmable-confirm": "{{GENDER:$1|Bi'j}} daor wisse van?",
+       "confirmable-confirm": "{{GENDER:$1|Bin jy}} dår wisse van?",
        "confirmable-yes": "Ja",
-       "confirmable-no": "Nee",
-       "thisisdeleted": "Bekieken of herstellen van $1?",
-       "viewdeleted": "Bekiek $1?",
-       "restorelink": "{{PLURAL:$1|versie die vortedaon is|versies die vortedaon bin}}",
-       "feedlinks": "Voer:",
-       "feed-invalid": "Voertype wörden niet ondersteunt.",
-       "feed-unavailable": "Syndicakievoer is niet beschikbaor",
-       "site-rss-feed": "$1 RSS-voer",
-       "site-atom-feed": "$1 Atom-voer",
-       "page-rss-feed": "\"$1\" RSS-voer",
-       "page-atom-feed": "\"$1\" Atom-voer",
+       "confirmable-no": "Ney",
+       "thisisdeleted": "Bekyken of herstellen van $1?",
+       "viewdeleted": "Bekyk $1?",
+       "restorelink": "{{PLURAL:$1|versy dee vordsmeaten is|versys dee vordsmeaten binnet}}",
+       "feedlinks": "Voder:",
+       "feed-invalid": "Vodertype wördt neet understöänt.",
+       "feed-unavailable": "Syndikatyvoder is neet beskikbår",
+       "site-rss-feed": "$1 RSS-voder",
+       "site-atom-feed": "$1 Atom-voder",
+       "page-rss-feed": "\"$1\" RSS-voder",
+       "page-atom-feed": "\"$1\" Atom-voder",
        "red-link-title": "$1 (syde besteyt noch neet)",
-       "sort-descending": "Aoflopend sorteren",
-       "sort-ascending": "Oplopend sorteren",
-       "nstab-main": "Artikel",
-       "nstab-user": "Gebruker",
-       "nstab-media": "Media",
+       "sort-descending": "Afloupend sorteren",
+       "sort-ascending": "Uploupend sorteren",
+       "nstab-main": "Syde",
+       "nstab-user": "Brukerssyde",
+       "nstab-media": "Mediasyde",
        "nstab-special": "Speciale syde",
        "nstab-project": "Projektsyde",
        "nstab-image": "Bestand",
-       "nstab-mediawiki": "Bericht",
+       "nstab-mediawiki": "Systeembericht",
        "nstab-template": "Mal",
        "nstab-help": "Hülpe",
        "nstab-category": "Kategory",
        "mainpage-nstab": "Vöärblad",
-       "nosuchaction": "De op-egeven haandeling besteet niet",
-       "nosuchactiontext": "De opdrachte in t webadres in ongeldig.\nJe hebben t webadres misschien verkeerd in-etikt of de verkeerde verwiezing evolgd.\nDit kan oek dujen op n fout in de programmatuur van {{SITENAME}}.",
-       "nosuchspecialpage": "Der besteet gien spesiale zied mit disse naam",
-       "nospecialpagetext": "<strong>Disse spesiale zied wörden niet herkend deur de programmatuur.</strong>\n\nn Lieste mit bestaonde spesiale ziejen ku'j vienen op [[Special:SpecialPages|{{int:specialpages}}]].",
-       "error": "Foutmelding",
-       "databaseerror": "Fout in de databanke",
-       "databaseerror-text": "Der is wat mis egaon bie n databankzeukopdrachte.\nDit kan betekenen dat der n fout in de programmtuur zit.",
-       "databaseerror-textcl": "Der is wat mis egaon bie n databankzeukopdrachte.",
-       "databaseerror-query": "Zeukopdrachte: $1",
-       "databaseerror-function": "Funksie: $1",
-       "databaseerror-error": "Fout: $1",
-       "laggedslavemode": "<strong>Waorschuwing:</strong> t is meugelik dat leste wiezigingen in de tekste van dit artikel nog niet verwarkt bin.",
+       "nosuchaction": "De upgeaven handeling besteyt neet",
+       "nosuchactiontext": "De updracht in et webadres in ungeldig.\nJy hebbet et webadres meskeen verkeyrd intyped of de verkeyrde verwysing volgd.\nDit kan ouk düden up een faut in de programmatuur van {{SITENAME}}.",
+       "nosuchspecialpage": "Der besteyt geen speciale syde mid disse name",
+       "nospecialpagetext": "<strong>Disse speciale syde wördt neet herkend döär de programmatuur.</strong>\n\nEen lyste mid bestånde speciale syden kün jy vinden up [[Special:SpecialPages|{{int:specialpages}}]].",
+       "error": "Faut",
+       "databaseerror": "Databankfaut",
+       "databaseerror-text": "Der is wat mis gån by een databanksöökupdracht.\nDit kan beteykenen dat der een faut in de programmtuur sit.",
+       "databaseerror-textcl": "Der is wat mis gån by een databanksöökupdracht.",
+       "databaseerror-query": "Söökupdracht: $1",
+       "databaseerror-function": "Funkty: $1",
+       "databaseerror-error": "Faut: $1",
+       "laggedslavemode": "<strong>Wårschüwing:</strong> et kan weasen dat de lätste wysigingen up disse syde noch neet upnöämen binnet.",
        "readonly": "De databanke is beveiligd",
-       "enterlockreason": "Waorumme en veur hoe lange is t eblokkeerd?",
-       "readonlytext": "De databanke van {{SITENAME}} is noen esleuten veur nieje bewarkingen en wiezigingen, warschienlik veur bestaandsonderhoud. De verantwoordelike systeembeheerder gaf hierveur de volgende reden op: '''$1'''",
-       "missing-article": "In de databanke steet gien tekste veur de zied \"$1\" die der wel in zol mutten staon ($2).\n\nDit kan koemen deurda'j n ouwe verwiezing naor t verschil tussen twee versies van n zied volgen of n versie opvragen die vortedaon is.\n\nAs dat niet zo is, dan he'j misschien n fout in de programmatuur evunnen.\nMeld t dan effen bie n [[Special:ListUsers/sysop|systeembeheerder]] van {{SITENAME}} en vermeld derbie de internetverwiezing van disse zied.",
-       "missingarticle-rev": "(versienummer: $1)",
-       "missingarticle-diff": "(Wieziging: $1, $2)",
-       "readonly_lag": "De databanke is automaties beveilig, zodat de ondergeschikten servers zich kunnen synchroniseren mit de sentrale server.",
-       "internalerror": "Interne fout",
-       "internalerror_info": "Interne fout: $1",
-       "filecopyerror": "Kon bestaand \"$1\" niet naor \"$2\" kopiëren.",
-       "filerenameerror": "Bestaandsnaamwieziging \"$1\" naor \"$2\" niet meugelik.",
-       "filedeleteerror": "Kon bestaand \"$1\" niet vortdoon.",
-       "directorycreateerror": "Map \"$1\" kon niet an-emaakt wörden.",
-       "directoryreadonlyerror": "De map \"$1\" is allinnig-lezen.",
-       "directorynotreadableerror": "De map \"$1\" kan niet elezen wörden.",
-       "filenotfound": "Kon bestaand \"$1\" niet vienen.",
-       "unexpected": "Onverwachten weerde: \"$1\"=\"$2\".",
-       "formerror": "Fout: kon formulier niet versturen",
-       "badarticleerror": "Disse haandeling kan op disse zied niet uutevoerd wörden.",
-       "cannotdelete": "De zied of t bestaand \"$1\" kon niet vortedaon wörden.\nt Kan ween dat n aander t al vortedaon hef.",
-       "cannotdelete-title": "Zied \"$1\" kan niet vortedaon wörden",
-       "delete-hook-aborted": "t Vortdoon wördt in t wiere eschopt deur n toepassige van MediaWiki.\nDer is gien veerdere informasie beschikbaor.",
-       "no-null-revision": "Kon gien lege nieje versie maken veur de zied \"$1\"",
-       "badtitle": "Ongeldige naam",
-       "badtitletext": "De naam van de op-evreugen zied is niet geldig, leeg, of n interwiki-verwiezing naor n onbekende of ongeldige wiki.",
-       "perfcached": "Disse gegevens koemen uut t tussengeheugen en bin misschien niet aktueel. Der {{PLURAL:$1|is hooguut een resultaot|bin hooguut $1 resultaoten}} beschikbaor in t tussengeheugen.",
-       "perfcachedts": "Disse gegevens koemen uut t tussengeheugen die veur t lest bie-ewörken is op $2 um $3. Der {{PLURAL:$4|is hooguut een resultaot|bin hooguut $4 resultaoten}} beschikbaor in t tussengeheugen.",
-       "querypage-no-updates": "'''Disse zied wördt niet meer bie-ewörken.'''",
-       "viewsource": "Brontekste bekyken",
-       "viewsource-title": "Bron bekieken van $1",
-       "actionthrottled": "Haandeling tegenehöllen",
+       "enterlockreason": "Voor een readen in vöär de vergrendeling, en geav up wanneyr et ungeaver vrygeaven wördt.",
+       "readonlytext": "De databanke is up et moment slöäten vöär nye inbreng en andere wysigingen, wårskynlik vöär rutinemåtig underhold, wårnå et weader lös geyt. \n\nDe systeembeheyrder gav hyrvöär de volgende readen up: $1",
+       "missing-article": "In de databanke steyt geen tekst vöär de syde \"$1\" dee der wel in sol mütten stån ($2).\n\nDit geböärt meystentyds as jy een olde verwysing nå et verskil tüsken twey versys van een syde volgen of as jy een versy upvrågen dee vordsmeaten is.\n\nAs dat neet so is, dan heb jy meskeen een faut in de programmatuur evünden.\nMeld et dan by een [[Special:ListUsers/sysop|systeembeheyrder]], en vermeld et webadres derby.",
+       "missingarticle-rev": "(versynummer: $1)",
+       "missingarticle-diff": "(Wysiging: $1, $2)",
+       "readonly_lag": "De databanke is automatisk vergrendeld terwyl de undergeskikede servers sik synchroniseren künnet mid de centrale server.",
+       "internalerror": "Interne faut",
+       "internalerror_info": "Interne faut: $1",
+       "filecopyerror": "Kun bestand \"$1\" neet nå \"$2\" kopieren.",
+       "filerenameerror": "\"$1\" kun neet hernöömd wörden nå \"$2\".",
+       "filedeleteerror": "Bestand \"$1\" kun neet vordsmeaten wörden.",
+       "directorycreateerror": "De map \"$1\" kun neet anmaked wörden.",
+       "directoryreadonlyerror": "De map \"$1\" is allinnig-leasen.",
+       "directorynotreadableerror": "De map \"$1\" kan neet leasen wörden.",
+       "filenotfound": "Bestand \"$1\" kun neet vünden wörden.",
+       "unexpected": "Unverwachtede waerde: \"$1\"=\"$2\".",
+       "formerror": "Faut: kun formulier neet verstüren",
+       "badarticleerror": "Disse handeling kan up disse syde neet uutvoord wörden.",
+       "cannotdelete": "De syde of et bestand \"$1\" kun neet vordsmeaten wörden.\nEt kan weasen dat een ander et al vordsmeaten hevt.",
+       "cannotdelete-title": "Syde \"$1\" kan neet vordsmeaten wörden",
+       "delete-hook-aborted": "Et vordsmyten wördt in et wyre skopped döär een topassing van MediaWiki.\nDer is wyder geen informaty beskikbår.",
+       "no-null-revision": "Kun geen leadige nye versy maken vöär de syde \"$1\"",
+       "badtitle": "Ungeldige name",
+       "badtitletext": "De name van de upvrågde syde is neet geldig, leadig, of der stünd een verkeyrde interspråk- of interwikiverwysing in.\nMöägelik binnet der eyn of meyr teykens bruked dee neet in titels tostån binnet.",
+       "perfcached": "Disse gegeavens kummen uut et tüskengehöägen en binnet meskeen neet aktueel. Der {{PLURAL:$1|is houguut eyn resultaat|binnet houguut $1 resultaten}} beskikbår in et tüskengehöägen.",
+       "perfcachedts": "Disse gegeavens kummen uut et tüskengehöägen dee vöär et lätst bywarked is up $2 üm $3. Der {{PLURAL:$4|is houguut eyn resultaat|binnet houguut $4 resultaten}} beskikbår in et tüskengehöägen.",
+       "querypage-no-updates": "Disse syde wördt neet bywarked.\nGegeavens up disse syde wördet neet vervarsd.",
+       "viewsource": "Brontekst bekyken",
+       "viewsource-title": "Bron bekyken van $1",
+       "actionthrottled": "Handeling teagenholden",
        "actionthrottledtext": "As maotregel tegen t plaotsen van alderhaande moek, is t antal keren da'j disse haandeling in n korte tied uutvoeren kunnen beteund. Je hebben de limiet overschrejen. Probeer t over n antal minuten weer.",
        "protectedpagetext": "Disse zied is beveiligd. Bewarken of aandere haandelingen bin niet meugelik.",
        "viewsourcetext": "Je kunnen de brontekste van disse zied bewarken en bekieken.",
        "logout": "Afmelden",
        "userlogout": "Aofmelden",
        "notloggedin": "Neet an-emelded",
-       "userlogin-noaccount": "Heb jy noch geen gebrukersname?",
+       "userlogin-noaccount": "Heb jy noch geen brukersname?",
        "userlogin-joinproject": "Wörd lid van {{SITENAME}}",
        "createaccount": "Inskryven",
        "userlogin-resetpassword-link": "Juuw wachtwoord vergeaten?",
        "pt-login": "Anmelden",
        "pt-login-button": "Anmelden",
        "pt-createaccount": "Inskryven",
-       "pt-userlogout": "Ofmelden",
+       "pt-userlogout": "Afmelden",
        "php-mail-error-unknown": "Der was n onbekende fout mit de mail()-funksie van PHP",
        "user-mail-no-addy": "Eprobeerd n berichjen te versturen zonder n netpostadres",
        "user-mail-no-body": "Der is eprobeerd n netbreef zonder tekste of mit n biester korte tekste te versturen.",
        "subject": "Onderwarp:",
        "minoredit": "kleine wysiging",
        "watchthis": "volg disse syde",
-       "savearticle": "Syde upslån",
-       "savechanges": "Wysigingen upslån",
+       "savearticle": "Syde uutgeaven",
+       "savechanges": "Wysigingen uutgeaven",
        "publishpage": "Zied uutbrengen",
-       "publishchanges": "Wysigingen üütbrengen",
+       "publishchanges": "Wysigingen uutgeaven",
        "preview": "Naokieken",
        "showpreview": "Bewarking nåkyken",
        "showdiff": "Verskil bekyken",
        "anoneditwarning": "<strong>Waorschuwing:</strong> je bin niet an-emeld.\nJoew IP-adres zal op-esleugen wörden a'j wiezigingen op disse zied anbrengen. A'j je eigen <strong>[$1 anmelden]</strong> of <strong>[$2 inschrieven]</strong> dan koemen joew bewarkingen onder joew gebrukersnaam te staon, samen mit aandere veurdelen.",
        "anonpreviewwarning": "''Je bin niet an-emeld.''\n''Deur de bewarking op te slaon wörden joew IP-adres op-esleugen in de ziedgeschiedenisse.''",
        "missingsummary": "'''Herinnering:''' je hebben gien samenvatting op-egeven veur de bewarking. A'j noen weer op ''Opslaon'' klikken wörden de bewarking zonder samenvatting op-esleugen.",
-       "missingcommenttext": "Plaots joew opmarking hieronder.",
+       "missingcommenttext": "Skryv een upmarking.",
        "missingcommentheader": "<strong>Waorschuwing:</strong> je hebben der gien onderwarptitel bie ezet. A'j noen weer op \"$1\" klikken, dan wörden de bewarking op-esleugen zonder onderwarptitel.",
-       "summary-preview": "Samenvatting naokieken:",
-       "subject-preview": "Onderwarp naokieken:",
+       "summary-preview": "Samenvatting nåkyken:",
+       "subject-preview": "Underwarp nåkyken:",
        "blockedtitle": "Gebruker is eblokkeerd",
-       "blockedtext": "'''Joew gebrukersnaam of IP-adres is eblokkeerd.'''\n\nJe bin eblokkeerd deur: $1.\nDe op-egeven reden is: ''$2''.\n\n* Eblokkeerd vanaof: $8\n* Eblokkeerd tot: $6\n* Bedoeld um te blokkeren: $7\n\nJe kunnen kontakt opnemen mit $1 of n aandere [[{{MediaWiki:Grouppage-sysop}}|beheerder]] um de blokkering te bepraoten.\nJe kunnen gien gebruukmaken van de funksie 'een bericht sturen', behalven a'j n geldig netpostadres op-egeven hebben in joew [[Special:Preferences|veurkeuren]] en t gebruuk van disse funksie niet eblokkeerd is.\nt IP-adres da'j noen gebruken is $3 en t blokkeringsnummer is #$5.\nVermeld t allebeie a'j argens op disse blokkering reageren.",
+       "blockedtext": "<strong>Juw brukersname of IP-adres is blokkeerd.</strong>\n\nJy binnet blokkeerd döär $1.\nDe upgeaven readen is <em>$2</em>.\n\n* Blokkeerd vanaf: $8\n* Blokkeerd tot: $6\n* Bedoold üm te blokkeren: $7\n\nJy künnet kontakt upneamen mid $1 of een andere [[{{MediaWiki:Grouppage-sysop}}|beheyrder]] üm de blokkering te bepråten.\nJy künnet de funkty \"{{int:emailuser}}\" neet bruken, behalven as jy een geldig e-postadres in juw [[Special:Preferences|instellingen]] upgeaven hebbet en et gebruuk van disse funkty neet blokkeerd is.\nEt IP-adres wat jy nu bruket is $3, en et blokkeringsnummer is #$5.\nVermeld de gegeavens dee hyrboaven stån as jy argens up disse blokkering reageren.",
        "autoblockedtext": "Joew IP-adres is automaties eblokkeerd umdat t gebruukt wördt deur n aandere gebruker, die eblokkeerd wördt deur $1.\nDe reden hierveur was:\n\n:''$2''\n\n* Begint: $8\n* Löp of nao: $6\n* Wee eblokkeerd wördt: $7\n\nJe kunnen kontakt opnemen mit $1 of n van de aandere\n[[{{MediaWiki:Grouppage-sysop}}|beheerders]] um de blokkering te bepraoten.\n\nNB: je kunnen de opsie \"n bericht sturen\" niet gebruken, behalven a'j n geldig netpostadres op-egeven hebben in de [[Special:Preferences|gebrukersveurkeuren]] en je niet eblokkeerd bin.\n\nJoew IP-adres is $3 en joew blokkeernummer is $5.\nGeef disse nummers deur a'j kontakt mit ene opnemen over de blokkering.",
        "blockednoreason": "gien reden op-egeven",
        "whitelistedittext": "Um ziejen te kunnen wiezigen, mu'j $1 ween",
        "accmailtext": "Der is n willekeurig wachtwoord veur [[User talk:$1|$1]] verstuurd naor $2. t Kan ewiezigd wörden op de zied ''[[Special:ChangePassword|wachtwoord wiezigen]]'' naoda'j an-emeld bin.",
        "newarticle": "(Niej)",
        "newarticletext": "Disse zied besteet nog niet.\nIn t veld hieronder ku'j wat schrieven um disse zied an te maken (meer informasie vie'j op de [$1 hulpzied]).\nA'j hier per ongelok terechtekeumen bin gebruuk dan de knoppe '''veurige''' um weerumme te gaon.",
-       "anontalkpagetext": "---- ''Disse overlegzied heurt bie n anonieme gebruker die nog gien gebrukersnaam hef, of t niet gebruukt. We gebruken daorumme t IP-adres um hum of heur te herkennen, mer t kan oek ween dat meerdere personen t zelfde IP-adres gebruken, en da'j hiermee berichten ontvangen die niet veur joe bedoeld bin. A'j dit veurkoemen willen, dan ku'j t best [[Special:CreateAccount|n gebrukersnaam anmaken]] of [[Special:UserLogin|anmelden]].''",
+       "anontalkpagetext": "----\n<em>Disse oaverlegsyde höyrt by een anonyme bruker dee noch geen brukersname hevt, of et neet bruukt.</em>\nDårümme bruken wy et IP-adresse ter identifikaty. Een IP-adresse kan döär meyrere lüde bruked wörden. As jy een anonyme bruker binnet, en et gevööl hebbet dat jy berichten kryget dee neet vöär ju bedoold binnet [[Special:CreateAccount|skryv ju eigen dan in]] of [[Special:UserLogin|meld ju eigen an]] üm verwarring mid andere anonyme brukers in de tokumst te vöärkommen.''",
        "noarticletext": "Der steyt nun geen tekst up disse syde.\nJy künnet [[Special:Search/{{PAGENAME}}|de titel upsöken]] in andere syden,\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} söken in de logboken],\nof [{{fullurl:{{FULLPAGENAME}}|action=edit}} disse syde anmaken]</span>.",
        "noarticletext-nopermission": "Op disse zied steet gien tekste.\nJe kunnen [[Special:Search/{{PAGENAME}}|zeuken naor disse term]] in aandere ziejen of\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} de logboeken deurzeuken]</span>, mer je hebben gien rechten um disse zied an te maken.",
        "missing-revision": "De versie #$1 van de zied \"{{FULLPAGENAME}} besteet niet.\n\nDit kömp meestentieds deur t volgen van n verouwerde verwiezing naor n zied die vortedaon is.\nWaorschienlik ku'j der meer gegevens over vienen in t [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} vortdologboek].",
        "userpage-userdoesnotexist": "Je bewarken n gebrukerszied van n gebruker die niet besteet (gebruker \"<nowiki>$1</nowiki>\"). Kiek effen nao o'j disse zied wel anmaken/bewarken willen.",
        "userpage-userdoesnotexist-view": "Gebruker \"$1\" steet hier niet in-eschreven",
        "blocked-notice-logextract": "Disse gebruker is op t moment eblokkeerd.\nDe leste regel uut t blokkeerlogboek steet hieronder as referensie:",
-       "clearyourcache": "'''Waort je:''' naodat de wiezigingen op-esleugen bin, mut t tussengeheugen van de webkieker nog eleegd wörden um t te kunnen zien. \n*'''Firefox / Safari:''' drok op ''Shift'' terwiel je op ''verniejen'' klikken, of gebruuk ''Ctrl-F5'' of ''Ctrl-R'' (''⌘-R'' op n knipperkiste van Mac)\n* '''Google Chrome:''' drok op ''Ctrl-Shift-R'' (''⌘-Shift-R'' op n knipperkiste van Mac)\n*'''Internet Explorer:''' drok op ''Ctrl'' terwiel je op ''verniejen'' klikken of drok op ''Ctrl-F5''\n*'''Opera:''' leeg t tussengeheugen in ''Extra → Voorkeuren\"",
+       "clearyourcache": "<strong>Upmarking:</strong> nå et seakeren, sül jy lichtkans et tüskengehöägen van juw webkyker mütten leadigen üm de wysigingen te seen.\n* <strong>Firefox / Safari:</strong> hold <em>Shift</em> indrükked terwyl jy up <em>Herladen</em> klikket, of drük up <em>Ctrl-F5</em> of <em>Ctrl-R</em> (<em>⌘-R</em> up een Mac)\n* <strong>Google Chrome:</strong> drük up <em>Ctrl-Shift-R</em> (<em>⌘-Shift-R</em> up een Mac)\n* <strong>Internet Explorer:</strong> hold <em>Ctrl</em> indrükked terwyl jy up <em>Herladen</em> klikket, of drük up <em>Ctrl-F5</em>\n* <strong>Opera:</strong> gå nå <em>Menü → Instellingen</em> (<em>Opera → Vöärköären</em> up een Mac) en dan nå <em>Privaatheid & beveiliging → Söökgeskydenisse wisken → Tydelike afbealdingen en bestanden</em>.",
        "usercssyoucanpreview": "'''Tip:''' gebruuk de knoppe \"{{int:showpreview}}\" um joew nieje css/js nao te kieken veurda'j t opslaon.",
        "userjsyoucanpreview": "'''Tip:''' gebruuk de knoppe \"{{int:showpreview}}\" um joew nieje css/js nao te kieken veurda'j t opslaon.",
        "usercsspreview": "'''Dit is allinnig n naokieksel van joew persoonlike CSS.'''\n'''t Is nog niet op-esleugen!'''",
        "templatesusedpreview": "{{PLURAL:$1|Mal|Mallen}} die in disse bewarking gebruukt wörden:",
        "templatesusedsection": "{{PLURAL:$1|Mal|Mallen}} die in dit subkopjen gebruukt wörden:",
        "template-protected": "(beveiligd)",
-       "template-semiprotected": "(half-beveiligd)",
+       "template-semiprotected": "(halv-beveiligd)",
        "hiddencategories": "Disse zied völt in de volgende verbörgen {{PLURAL:$1|kategorie|kategorieën}}:",
        "edittools": "<!-- Disse tekste steet onder de bewarkings- en bestaandinlaodformulieren. -->",
        "nocreatetext": "Disse webstee hef de meugelikheid um nieje ziejen an te maken beteund. Je kunnen ziejen die al bestaon wiezigen of je kunnen je [[Special:UserLogin|anmelden of n gebrukerszied anmaken]].",
        "histfirst": "Eerste",
        "histlast": "Leste",
        "historysize": "({{PLURAL:$1|1 byte|$1 bytes}})",
-       "historyempty": "(leeg)",
+       "historyempty": "leadig",
        "history-feed-title": "Wiezigingsoverzichte",
        "history-feed-description": "Wiezigingsoverzichte veur disse zied op de wiki",
        "history-feed-item-nocomment": "$1 op $2",
        "prevn-title": "{{PLURAL:$1|Veurig resultaot|Veurige $1 resultaoten}}",
        "nextn-title": "{{PLURAL:$1|Volgend resultaot|Volgende $1 resultaoten}}",
        "shown-title": "Låt $1 {{PLURAL:$1|resultaat|resultaten}} per syde seen",
-       "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3)",
+       "viewprevnext": "($1 {{int:pipe-separator}} $2) ($3) bekyken.",
        "searchmenu-exists": "'''Der is n zied mit de naam \"[[:$1]]\" op disse wiki.'''",
        "searchmenu-new": "<strong>De zied \"[[:$1]]\" op disse wiki anmaken!</strong> \n{{PLURAL:$2|0=|Zie oek de zied mit joew zeukresultaoten.|Zie oek de lieste mit evunnen zeukresultaoten.}}",
        "searchprofile-articles": "Artikels",
        "searchprofile-advanced-tooltip": "Söken in de angeaven naamruumden",
        "search-result-size": "$1 ({{PLURAL:$2|1 woord|$2 woorden}})",
        "search-result-category-size": "{{PLURAL:$1|1 kategorielid|$1 kategorielejen}} ({{PLURAL:$2|1 onderkategorie|$2 onderkategorieën}}, {{PLURAL:$3|1 bestaand|$3 bestaanden}})",
-       "search-redirect": "(deurverwiezing vanaof $1)",
+       "search-redirect": "(döärverwysing vanaf $1)",
        "search-section": "(onderwarp $1)",
        "search-file-match": "(kümt oavereyne mid de inhold van et bestand)",
        "search-suggest": "Bedoelden je: $1",
-       "search-interwiki-caption": "Zusterprojekten",
+       "search-interwiki-caption": "Resultaten van süsterprojekten",
        "search-interwiki-default": "Resultaoten van $1:",
        "search-interwiki-more": "(meer)",
        "search-relatedarticle": "Verwaant",
        "searchall": "alles",
        "showingresults": "Hieronder {{PLURAL:$1|steet '''1''' resultaot|staon '''$1''' resultaoten}}  <b>$1</b> vanaof nummer <b>$2</b>.",
        "search-showingresults": "{{PLURAL:$4|Resultaot <strong>$1</strong> van <strong>$2</strong>|Resultaoten <strong>$1 - $2</strong> van <strong>$3</strong>}}",
-       "search-nonefound": "Der bin gien resultaoten veur de zeukopdrachte.",
+       "search-nonefound": "Der binnet geen resultaten vöär de söökupdrachte.",
        "powersearch-legend": "Uutgebreid zeuken",
        "powersearch-ns": "Zeuken in naamruumten:",
        "powersearch-togglelabel": "Selekteren:",
        "action-editmyprivateinfo": "joew eigen priveegegevens bewarken",
        "nchanges": "$1 {{PLURAL:$1|wieziging|wiezigingen}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|sinds joew leste bezeuk}}",
-       "enhancedrc-history": "geschiedenisse",
+       "enhancedrc-history": "geskydenisse",
        "recentchanges": "Lätste wysigingen",
        "recentchanges-legend": "Optys vöär lätste wysigingen",
        "recentchanges-summary": "Up disse syde kün jy de lätste wysigingen van disse wiki bekyken.",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}}<br />(see ouk de [[Special:NewPages|lyste mid nye syden]])",
        "recentchanges-submit": "Bekiek",
        "rcfilters-legend-heading": "<strong>Lyste mid afkortingen:</strong>",
-       "rcfilters-group-results-by-page": "Resultaoten per zied groeperen",
+       "rcfilters-group-results-by-page": "Resultaten per syde grupperen",
        "rcfilters-activefilters": "Aktive filters",
        "rcfilters-activefilters-hide": "Verbarg",
        "rcfilters-activefilters-show": "Bekiek",
        "rcfilters-activefilters-hide-tooltip": "Verbarg aktive filters",
        "rcfilters-activefilters-show-tooltip": "Laot aktive filters seen",
-       "rcfilters-limit-title": "Resultåten üm te låten seen",
+       "rcfilters-limit-title": "Resultaten üm te låten seen",
        "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|wysiging|wysigingen}}, $2",
        "rcfilters-date-popup-title": "Tydsperiode üm te döärsöken",
        "rcfilters-days-title": "De vöärbye dagen",
        "rcfilters-hours-title": "De lätste uren",
        "rcfilters-days-show-days": "$1 {{PLURAL:$1|dag|dagen}}",
        "rcfilters-days-show-hours": "$1 {{PLURAL:$1|uur|uren}}",
-       "rcfilters-quickfilters": "Upeslöägen filters",
+       "rcfilters-quickfilters": "Seakerde filters",
        "rcfilters-quickfilters-placeholder-title": "Noch geen filters up-eslöägen",
-       "rcfilters-quickfilters-placeholder-description": "Üm juuw filterinstellingen up te slån en et låter te gebruken, klik up et bladwyserikoon underan by \"Aktive filters\".",
+       "rcfilters-quickfilters-placeholder-description": "Üm juw filterinstellingen te seakeren en et later te herbruken, klik up et bladwyserpiktogram underan by \"Aktive filters\".",
        "rcfilters-savedqueries-apply-label": "Instellingen opslaon",
        "rcfilters-savedqueries-cancel-label": "Aofbreken",
-       "rcfilters-savedqueries-add-new-title": "Filterinstellingen upslån",
+       "rcfilters-savedqueries-add-new-title": "Filterinstellingen seakeren",
        "rcfilters-restore-default-filters": "Standardfilters weerummezetten",
        "rcfilters-clear-all-filters": "Alle filters vortdoon",
        "rcfilters-show-new-changes": "Låt nyste wysigingen seen",
-       "rcfilters-search-placeholder": "Filter wysigingen (gebrüük et menü of söök up filtername)",
+       "rcfilters-search-placeholder": "Filter wysigingen (bruuk et menü of söök up filtername)",
        "rcfilters-filterlist-feedbacklink": "Låt uns weaten wat jy van disse (nye) filterhülpmiddels vinden",
-       "rcfilters-highlightbutton-title": "Resultåten markeren",
+       "rcfilters-highlightbutton-title": "Resultaten markeren",
        "rcfilters-highlightmenu-title": "Kies n kleur",
        "rcfilters-filtergroup-user-experience-level": "Gebrukersanmelding en ervåring",
        "rcfilters-filter-user-experience-level-registered-label": "An-emeld",
        "rcfilters-filter-user-experience-level-newcomer-label": "Anwas",
        "rcfilters-filter-user-experience-level-newcomer-description": "An-emelden bewarkers dee minder as 10 bewarkingen edån hebben of 4 dagen aktiv ewesd hebben.",
        "rcfilters-filter-user-experience-level-learner-label": "Leyrlingen",
-       "rcfilters-filter-user-experience-level-learner-description": "An-emelde bewarkers mid meyr ervåring as \"anwas\", mär minder as \"ervåren gebrukers\".",
+       "rcfilters-filter-user-experience-level-learner-description": "Anmeldede bewarkers mid meyr ervaring as \"anwas\", mär minder as \"ervaren brukers\".",
        "rcfilters-filter-user-experience-level-experienced-label": "Ervåren gebrukers",
        "rcfilters-filter-user-experience-level-experienced-description": "An-emelde bewarkers mid meyr as 500 bewarkingen en 30 dagen van aktiviteit.",
        "rcfilters-filter-bots-label": "Bot",
        "rcfilters-filter-pageedits-label": "Sydbewarkingen",
        "rcfilters-filter-pageedits-description": "Wysigingen an de wiki-inhold, diskussys, kategorybeskryvingen…",
        "rcfilters-filter-newpages-label": "Nye syden",
-       "rcfilters-filter-newpages-description": "Bewarkingen wårmead jy een nye syde anmaken.",
+       "rcfilters-filter-newpages-description": "Bewarkingen wårmead jy een nye syde anmaket.",
        "rcfilters-filter-categorization-label": "Kategorywysigingen",
        "rcfilters-filter-categorization-description": "Upgave van syden dee to-evoogd of vordedån wörden uut kategoryen.",
-       "rcfilters-filter-logactions-label": "Eregistreerde aktys",
+       "rcfilters-filter-logactions-label": "Registreerde aktys",
        "rcfilters-filter-logactions-description": "Administrative handelingen, nye kontos, vordedåne syden, upladingen…",
        "rcfilters-filtergroup-lastrevision": "Lätste versys",
        "rcfilters-filter-lastrevision-label": "Lätste versy",
        "rcfilters-filter-previousrevision-label": "Neet de lätste versy",
        "rcfilters-filter-previousrevision-description": "Alle wysigingen dee neet de \"lätste versy\" binnen.",
        "rcfilters-view-tags": "Emarkeerde wysigingen",
-       "rcfilters-view-namespaces-tooltip": "Filter resultåten up naamruumte",
-       "rcfilters-view-tags-tooltip": "Filter resultåten döär gebrüük te maken van bewarkingsetiketten",
+       "rcfilters-view-namespaces-tooltip": "Filter resultaten up naamruumde",
+       "rcfilters-view-tags-tooltip": "Filter resultaten döär bewarkingsetiketten te bruken",
        "rcfilters-liveupdates-button": "Rechtstreakse aktualisering",
        "rcfilters-liveupdates-button-title-off": "Nye wysigingen voorddalik låten seen",
        "rcnotefrom": "Wysigingen sinds <strong>$3, $4</strong> (maximaal <strong>$1</strong> {{PLURAL:$1|wysiging|wysigingen}}).",
        "rclistfrom": "Bekyk wysigingen vanaf $3 $2",
        "rcshowhideminor": "$1 kleine wysigingen",
        "rcshowhideminor-show": "Bekiek",
-       "rcshowhideminor-hide": "Verbarg",
+       "rcshowhideminor-hide": "verbargen",
        "rcshowhidebots": "$1 botbrukers",
-       "rcshowhidebots-show": "Bekiek",
+       "rcshowhidebots-show": "bekyken",
        "rcshowhidebots-hide": "Verbarg",
        "rcshowhideliu": "$1 registreerde brukers",
        "rcshowhideliu-show": "Bekiek",
-       "rcshowhideliu-hide": "Verbarg",
-       "rcshowhideanons": "$1 anonime brukers",
+       "rcshowhideliu-hide": "verbargen",
+       "rcshowhideanons": "$1 anonyme brukers",
        "rcshowhideanons-show": "Bekiek",
-       "rcshowhideanons-hide": "Verbarg",
+       "rcshowhideanons-hide": "verbargen",
        "rcshowhidepatr": "$1 nao-ekeken bewarkingen",
        "rcshowhidepatr-show": "Bekiek",
        "rcshowhidepatr-hide": "Verbarg",
        "rcshowhidemine": "$1 myn bewarkingen",
        "rcshowhidemine-show": "Bekiek",
-       "rcshowhidemine-hide": "Verbarg",
+       "rcshowhidemine-hide": "verbargen",
        "rcshowhidecategorization": "$1 kategorisering van ziejen",
        "rcshowhidecategorization-show": "Bekiek",
        "rcshowhidecategorization-hide": "Verbarg",
        "recentchangeslinked-feed": "Volg verwysingen",
        "recentchangeslinked-toolbox": "Volg verwysingen",
        "recentchangeslinked-title": "Wiezigingen verwaant an $1",
-       "recentchangeslinked-summary": "Op disse spesiale zied steet n lieste mit de leste wieziginen op ziejen waornaor verwezen wördt. Ziejen op [[Special:Watchlist|joew volglieste]] staon '''vet'''.",
+       "recentchangeslinked-summary": "Voor een sydname in üm bewarkingen te seen up syden wårnå verweasen wördt of dårnå verwysen. (Voor {{ns:category}}:kategoryname in üm leaden van een kategory te seen). Bewarkingen van syden up [[Special:Watchlist|juw volglyste]] binnet <strong>vetdrükked</strong>.",
        "recentchangeslinked-page": "Ziednaam:",
        "recentchangeslinked-to": "Bekiek wiezigingen op ziejen mit verwiezingen naor disse zied",
        "recentchanges-page-added-to-category": "[[:$1]] bie kategorie ezet",
        "namespace_association": "Bybehöyrende naamruumde",
        "tooltip-namespace_association": "Vink dit vakjen an um ouk de oaverleg- en underwarpnaamruumde in te slüten dee by de selekteerde naamruumde höyret.",
        "blanknamespace": "(Höyvdnaamruumde)",
-       "contributions": "{{GENDER:$1|Gebrukersbydragen}}",
+       "contributions": "{{GENDER:$1|Brukersbydragen}}",
        "contributions-title": "Biedragen van $1",
        "mycontris": "Myn bydragen",
        "anoncontribs": "Bydragen",
        "tooltip-pt-preferences": "{{GENDER:|Miene}} vuurkeuren",
        "tooltip-pt-watchlist": "Lieste van zieden die op miene volglieste stoan",
        "tooltip-pt-mycontris": "Oaverzicht van {{GENDER:|oew}} biejdreagen",
-       "tooltip-pt-login": "Jy wördt van harte uutnöygd üm ju an te melden as bruker, mar et is neet verplicht",
+       "tooltip-pt-login": "Jy wördet van harte uutnöygd üm ju an te melden as bruker, mär et is neet verplicht",
        "tooltip-pt-logout": "Ofmaelden",
        "tooltip-pt-createaccount": "Skryv juw eigen vöäral in en meld juw eigen an. Dit is lykewels neet verplicht.",
        "tooltip-ca-talk": "Låt een oaverlegtekst oaver disse syde seen",
        "yesterday-at": "Gisteren um $1",
        "bad_image_list": "De opmaak is as volgt:\n\nAllinnig regels in n lieste (regels die beginnen mit *) wörden verwarkt.\nDe eerste verwiezing op n regel mut n verwiezing ween naor n ongewunst bestaand.\nAlle volgende verwiezingen die op de zelfde regel staon, wörden behaandeld as uutzundering, zo as ziejen waorop t bestaand in te tekste op-eneumen is.",
        "metadata": "Metadata",
-       "metadata-help": "In dit bestaand zit metadata mit EXIF-informasie, die deur n fotokamera, inleesapparaot of fotobewarkingsprogramma op-estuurd kan ween.",
+       "metadata-help": "Dit bestand bevat ekstra informaty, dee wårskynlik döär een fotokamera, skänner of fotobewarkingsprogramma upladen binnet.\nAs dit betand bewarked is, kommen möägelik bepålde details neet oavereyne mid et ewysigde bestand.",
        "metadata-expand": "Bekiek uutebreiden gegevens",
        "metadata-collapse": "Verbarg uutebreiden gegevens",
        "metadata-fields": "De afbealdingsmetadatavelden in dit bericht ståt ouk up een afbealdingssyde as de metadatatabel inklapped is.\nAndere velden wördet verbörgen.\n* make\n* model\n* datetimeoriginal\n* exposuretime\n* fnumber\n* isospeedratings\n* focallength\n* artist\n* copyright\n* imagedescription\n* gpslatitude\n* gpslongitude\n* gpsaltitude",
        "confirm-purge-title": "Herny disse syde",
        "confirm_purge_button": "Bevestig",
        "confirm-purge-top": "Klik up 'bevestig' üm et tüskengehöägen van disse syde te leagen.",
-       "confirm-purge-bottom": "Et leagmaken van et tüskengehöägen sörgt dervöär dat jy de lätste versy van een syde te seen krygen.",
+       "confirm-purge-bottom": "Et leadigmaken van et tüskengehöägen sörgt dervöär dat jy de lätste versy van een syde te seen kryget.",
        "confirm-watch-button": "Oké",
        "confirm-watch-top": "Disse zied op joew volglieste zetten?",
        "confirm-unwatch-button": "Oké",
        "compare-invalid-title": "De titel die'j op-egeven hebben, is ongeldig.",
        "compare-title-not-exists": "De titel die'j op-egeven hebben, besteet niet.",
        "compare-revision-not-exists": "De versie die'j op-egeven hebben, besteet niet.",
-       "diff-form": "een '''formelier'''",
+       "diff-form": "Wysigingen",
        "dberr-problems": "t Spiet ons, mer disse webstee hef op t moment wat techniese problemen.",
        "dberr-again": "Wach n paor minuten en probeer t daornao opniej.",
        "dberr-info": "(Kan gien verbiending maken mit de databankeserver: $1)",
        "expandtemplates": "Mallen substitueren",
        "expand_templates_intro": "Disse spesiale zied leest de op-egeven tekste en substitueert rekursief alle mallen in de tekste. Oek ondersteunde parserfunksies zo as <code><nowiki>{{</nowiki>#language:…}}</code> en variabels zo as <nowiki>{{</nowiki>CURRENTDAY}}&mdash. Zwat alle teksten tussen dubbelde krulhaken wörden esubstitueerd.",
        "expand_templates_title": "Titel, veur {{FULLPAGENAME}}, enz.:",
-       "expand_templates_input": "Invoertekste:",
+       "expand_templates_input": "Wikitekst invoren:",
        "expand_templates_output": "Resultaot",
        "expand_templates_xml_output": "XML-uutvoer",
        "expand_templates_ok": "Oké",
        "special-characters-title-minus": "minteken",
        "mw-widgets-abandonedit": "Bi'j der wisse van da'j de naokiekmodus verlaoten willen zonder eerst op te slaon?",
        "mw-widgets-abandonedit-discard": "Wiezigingen vortsmieten",
-       "mw-widgets-abandonedit-keep": "Verdan gaon mit bewarken",
-       "mw-widgets-abandonedit-title": "Wee'j t zeker?",
+       "mw-widgets-abandonedit-keep": "Vöärdan gån mid bewarken",
+       "mw-widgets-abandonedit-title": "Bin jy dår wisse van?",
        "randomrootpage": "Willeköärige stamsyde"
 }
index a2e6203..6b35dab 100644 (file)
        "category-empty": "''यो श्रेणीमा हाल कुनै पृष्ठ या मिडियाहरु रहेका छैनन् ।''",
        "hidden-categories": "{{PLURAL:$1|लुकाइएको श्रेणी|लुकाइएका श्रेणीहरू}}",
        "hidden-category-category": "लुकाइएका श्रेणीहरू",
-       "category-subcat-count": "{{PLURAL:$2|यो श्रेणीमा निम्न उपश्रेणीहरू मात्र छन्।|यो श्रेणीको निम्न {{PLURAL:$1|उपश्रेणी|$1 उपश्रेणीहरू}},  $2 कुल मध्ये श्रेणीहरू छन् ।}}",
+       "category-subcat-count": "{{PLURAL:$2|यो श्रेणीमा निम्न उपश्रेणीहरू मात्र छन्।|यो श्रेणीको निम्न {{PLURAL:$1|उपश्रेणी|$1 उपश्रेणीहरू}}, $2 कुल मध्ये श्रेणीहरू छन्।}}",
        "category-subcat-count-limited": "यो श्रेणीमा निम्न {{PLURAL:$1|उपश्रेणी|$1 उपश्रेणीहरू}} छन् ।",
-       "category-article-count": "{{PLURAL:$2|यो श्रेणीमा एक मात्र पृष्ठरहेको छ।|कुल $2 मध्ये यो श्रेणीमा {{PLURAL:$1|पृष्ठ|$1 पृष्ठहरू}} रहेका छन् । }}",
+       "category-article-count": "{{PLURAL:$2|यो श्रेणीमा एक मात्र पृष्ठरहेको छ।|कुल $2 मध्ये यो श्रेणीमा {{PLURAL:$1|पृष्ठ|$1 पृष्ठहरू}} रहेका छन्}}",
        "category-article-count-limited": "निम्न {{PLURAL:$1|पृष्ठ|$1 पृष्ठहरू}} यस श्रेणीमा रहेको ।",
        "category-file-count": "{{PLURAL:$2|यो श्रेणीमा निम्न फाइल मात्र छ ।|निम्न श्रेणीमा {{PLURAL:$1|फाइल|$1 फाइलहरू}} , कुल  $2 मध्ये रहेको ।}}",
        "category-file-count-limited": "निम्न  {{PLURAL:$1|फाइल|$1 फाइलहरू}} यस श्रेणीमा रहेको ।",
        "history": "पृष्ठको इतिहास",
        "history_short": "पृष्ठको इतिहास",
        "history_small": "इतिहास",
-       "updatedmarker": "मà¥\87रो अन्तिम भ्रमण पछि अद्यतन गरिएको",
+       "updatedmarker": "तपाà¤\88à¤\81à¤\95ो अन्तिम भ्रमण पछि अद्यतन गरिएको",
        "printableversion": "छाप्नयोग्य संस्करण",
        "permalink": "स्थायी लिङ्क",
        "print": "छाप्नुहोस्",
        "newarticle": "(नयाँ)",
        "newarticletext": "तपाईंले अहिले सम्म नभएको पृष्ठको लिङ्क पहिल्याउनु भएको छ।\nयो पृष्ठ निर्माण गर्न तलको कोष्ठमा टाइप गर्नुहोस्  ।(थप जानकारीको लागि [$1 help page] हेर्नुहोस् )।\nयहाँ त्यत्तिकै आइपुग्नु भएको हो भने , ब्राउजरको  '''back''' बटन थिच्नुहोस् ।",
        "anontalkpagetext": "----''यो वार्तालाप पृष्ठ अज्ञात प्रयोगकर्ताको हो जसले अहिलेसम्म खाता बनाएकै छैन, अथवा जसले यस पृष्ठको उपयोग गर्दैन।\nयस कारण हामीले उसलाई उसको आइपी ठेगानाले चिन्न सक्छौं। \nयस्तो आइपी ठेगाना धेरै प्रयोगकर्ताहरूको साझा हुनसक्छ।\nयदि तपाईं अज्ञात प्रयोगकर्ता हुनुहुन्छ र तपाईंमाथि नचाहिँदो टिप्पणी भएको अनुभव गर्नुहुन्छ भने भविष्यमा अन्य अज्ञात प्रयोगकर्तासित अलमलिनबाट बच्न कृपया [[Special:CreateAccount|खाता खोल्नुहोस्]] अथवा [[Special:UserLogin|प्रवेश गर्नुहोस्]] ''",
-       "noarticletext": "यस लेखमा अहिले केहि पनि पाठ छैन ।\nतपाईंले अन्य पृष्ठमा [[Special:Search/{{PAGENAME}}|यस पृष्ठको शीर्षकको लागि खोज]] गर्न सक्नुहुन्छ ।\n<span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} पृष्ठ सम्बन्धित ढड्डामा खोज],\nवा [{{fullurl:{{FULLPAGENAME}}|action=edit}}  यसै पृष्ठलाई सम्पादन गर्ने]</span>.",
+       "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}}|पृष्ठ={{FULLPAGENAMEE}}}} सम्बन्धित लगहरू खोज्न सक्नुहुनेछ ]</span> तर तपाईंलाई नयाँ पृष्ठ बनाउने अधिकार छैन।",
        "missing-revision": "\"{{FULLPAGENAME}}\" पृष्ठको अवतरण #$1 रहेको छैन।\n\nसामान्य रूपमा यसो एउटा हटाइएको पृष्ठको पुरानो लिङ्कमा क्लिक गर्दा हुन्छ।\nअधिक जानकारीको लागि तपाईं [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} हटाएको लग] हेर्न सक्नुहुन्छ।",
        "userpage-userdoesnotexist": "प्रयोगकर्ताको खाता  \"<nowiki>$1</nowiki>\" दर्ता गरिएको छैन ।\nतपाईंले पृष्ठ निर्माण/सम्पादन गर्न चाहनु भएको भए जाँच गर्नुहोस् ।",
        "rev-deleted-text-view": "यस पृष्ठको संशोधन '''मेटिएकोछ'''।\nतपाईंले हेर्न सक्नुहुन्छ; [{{fullurl:{{#Special:Log}}/delete|page={{FULLPAGENAMEE}}}} मेटिएको लगमा विवरण पाउन सकिन्छ]।",
        "rev-suppressed-text-view": "यस पृष्ठको पुनरावलोकन <strong>थिचिएको छ</strong>।\nप्रबन्धकको हैसियतले हेर्न सक्नुहुन्छ; [{{fullurl:{{#Special:Log}}/delete|पृष्ठ={{FULLPAGENAMEE}}}}को थिचिएको लगमा विवरण पाउन सकिन्छ]",
        "rev-deleted-no-diff": "तपाईंले यसको भिन्नता पाउन सक्नुहुन्न किनभने यस पृष्ठको पुनरावलोकन <strong>मेटाइएको छ</strong>'।\nयसको विवरण [{{fullurl:{{#Special:Log}}/delete|पृष्ठ={{FULLPAGENAMEE}}}}को मेटाइएको लगमा पाउन सक्नुहुन्छ]।",
-       "rev-suppressed-no-diff": "तपाà¤\88à¤\82 यसको भिन्नता हेर्न सक्नुहुन्न किनभने यसको एउटा संशोधन <strong>मेटाइएको</strong>छ।",
+       "rev-suppressed-no-diff": "तपाà¤\88à¤\81 यसको भिन्नता हेर्न सक्नुहुन्न किनभने यसको एउटा संशोधन <strong>मेटाइएको</strong>छ।",
        "rev-deleted-unhide-diff": "यस पृष्ठका पुनरावलोकनहरू मध्ये एउटा भिन्नता <strong>मेटाइएकोछ</strong>।\nयसको पूर्ण विवरण [{{fullurl:{{#Special:Log}}/delete|पृष्ठ={{FULLPAGENAMEE}}}}को मेटाइएको लगमा पाउन सकिन्छ]।\nयदि चाहनु भयो भने प्रवन्धकको हैसियतले [यो भिन्नता $1] हेर्न सक्नुहुन्छ।",
        "rev-suppressed-unhide-diff": "यस पृष्ठको पुनरावलोकनहरू मध्ये एउटा भिन्नता <strong>थिचिएको छ</strong>।\nयसको पूर्ण विवरण [{{fullurl:{{#Special:Log}}/suppress|पृष्ठ={{FULLPAGENAMEE}}}}को थिचिएको लगमा पाउन सकिन्छ]।\nयदि चाहनु भयो भने प्रबन्धकको हैसियतमा [यो भिन्नता $1] हेर्न सक्नुहुन्छ।",
        "rev-deleted-diff-view": "यस भिन्नताका संशोधनहरू मध्येको एउटा चाहिं <strong>मेटियो।<strong> \nतपाईंले यस भिन्नतालाई हेर्न सक्नुहुन्छ; सबै विवरण  [{{fullurl:{{#Special:Log}}/delete|पृष्ठ={{FULLPAGENAMEE}}}} मेटाइएको लग]मा पाउन सकिनेछ।",
        "difference-title": "\"$1\" को बिचमा भिन्नता",
        "difference-title-multipage": "\"$1\" तथा \"$2\" को बिचमा भिन्नता",
        "difference-multipage": "(पृष्ठहरूमा भिन्नता)",
-       "lineno": "पà¤\82क्ति $1:",
+       "lineno": "पà¤\99à¥\8dक्ति $1:",
        "compareselectedversions": "छानिएका संस्करणहरू दाँज्नुहोस्",
        "showhideselectedversions": "छानिएका पुनरावलोकनहरू देखाउने/लुकाउने",
        "editundo": "रद्द गर्ने",
        "recentchanges-label-minor": "यो साधारण सम्पादन हो",
        "recentchanges-label-bot": "यो सम्पादन बोटद्वारा गरिएको थियो",
        "recentchanges-label-unpatrolled": "यो सम्पादन अहिले सम्म गस्ती गरिएको छैन",
-       "recentchanges-label-plusminus": "यति बाइटहरू संख्याले पृष्ठको आकार परिवर्तन भएको छ",
+       "recentchanges-label-plusminus": "यति बाइट सङ्ख्याले यस पृष्ठको आकार परिवर्तन भएको छ",
        "recentchanges-legend-heading": "<strong>आदर्श वाक्य:</strong>",
        "recentchanges-legend-newpage": "{{int:recentchanges-label-newpage}} ([[Special:NewPages|नयाँ पृष्ठहरूको सूची]] यो पनि हेर्नुहोस्)",
        "recentchanges-legend-plusminus": "(''±१२३'')",
        "rcfilters-filter-categorization-label": "परिवर्तित श्रेणी",
        "rcfilters-filter-lastrevision-label": "हालको संस्करण",
        "rcnotefrom": "तल <strong>$2</strong> देखि (<strong>$1</strong> सम्म) {{PLURAL:$5|भएका परिवर्तनहरू देखाइएको छ|भएका परिवर्तनहरू देखाइन्छ}}।",
-       "rclistfrom": "$3 $2 देखिका नयाँ परिवर्तनहरू देखाउनु",
+       "rclistfrom": "$3 $2 देखिका नयाँ परिवर्तनहरू देखाउनुहोस्",
        "rcshowhideminor": "$1 सामान्य सम्पादन",
        "rcshowhideminor-show": "देखाउनुहोस्",
        "rcshowhideminor-hide": "लुकाउनुहोस्",
        "recentchangeslinked-feed": "सम्बन्धित परिवर्तनहरू",
        "recentchangeslinked-toolbox": "सम्बन्धित परिवर्तनहरू",
        "recentchangeslinked-title": "\"$1\" सँग सम्बन्धित परिवर्तन",
-       "recentchangeslinked-summary": "कुनै पृष्ठको वा  यससँग सम्बन्धित परिवर्तन हेर्नको लागि उक्त पृष्ठको नाम हाल्नुहोस। (कुनै श्रेणीको सामाग्रीहरुको लागि {{ns:category}}: श्रेणीको नाम हल्नुहोस ।  [[Special:Watchlist|तपाईंको अवलोकन सूची]]का पृष्ठहरू <strong>गाढा अक्षरमा</strong> छन् ।",
+       "recentchangeslinked-summary": "कुनै पृष्ठको वा यससँग सम्बन्धित परिवर्तन हेर्नको लागि उक्त पृष्ठको नाम हाल्नुहोस्। (कुनै श्रेणीको सामाग्रीहरूको लागि {{ns:category}}:श्रेणीको नाम) हाल्नुहोस्।  [[Special:Watchlist|तपाईँको अवलोकन सूची]]का पृष्ठहरू <strong>गाढा अक्षरमा</strong> छन्।",
        "recentchangeslinked-page": "पृष्ठ नाम:",
        "recentchangeslinked-to": "यसको सट्टा यो पृष्ठसँग जोडिएका पृष्ठहरूको परिवर्तन देखाउने",
        "upload": "फाइल उर्ध्वभरण",
        "filehist-filesize": "फाइल आकार",
        "filehist-comment": "टिप्पणी",
        "imagelinks": "फाइलको प्रयोगहरू",
-       "linkstoimage": "यस फाइलमा निम्न{{PLURAL:$1|पृष्ठ जोडिन्छ|$1 पृष्ठहरू जोडिन्छन्}}:",
+       "linkstoimage": "यस फाइलमा निम्न {{PLURAL:$1|पृष्ठ जोडिन्छ|$1 पृष्ठहरू जोडिन्छन्}}:",
        "linkstoimage-more": "$1 भन्दा अधिक {{PLURAL:$1|पृष्ठ लिङ्क|पृष्ठ लिङ्कहरू}} यस फाइलसँग जोडिएको छ। \nनिम्नलिखित सूची फाइलसँग {{PLURAL:$1|पहिलो पृष्ठ लिङ्क|पहिलो $1 पृष्ठ लिङ्कहरू}} जोडिने देखाउँछ।\n[[Special:WhatLinksHere/$2|पूर्ण सूची]] पनि उपलब्ध छ।",
-       "nolinkstoimage": "यà¥\8b à¤«à¤¾à¤\88लसà¤\82à¤\97 à¤²à¤¿à¤\82à¤\95भà¤\8fà¤\95à¥\8b à¤\95à¥\81नà¥\88 à¤ªà¥\83षà¥\8dठ à¤\9bà¥\88न.",
+       "nolinkstoimage": "यà¥\8b à¤«à¤¾à¤\87लसà¤\81à¤\97 à¤\95à¥\81नà¥\88 à¤ªà¤¨à¤¿ à¤ªà¥\83षà¥\8dठ à¤\9cà¥\8bडिà¤\8fà¤\95à¥\8b à¤\9bà¥\88न।",
        "morelinkstoimage": "यस फाइलको [[Special:WhatLinksHere/$1|थप लिंकहरू]] हेर्नुहोस् ।",
        "linkstoimage-redirect": "$1 (फाइल अनुप्रेषण) $2",
        "duplicatesoffile": "निम्नलिखित {{PLURAL:$1|फाइलको प्रतिलिपि हो|$1 फाइलहरूको प्रतिलिपि हो}} ([[Special:FileDuplicateSearch/$2|अधिक जानकारीहरू]]):",
        "rollback-success": "$1द्वारा उल्टाइएका सम्पादनहरू;\nपछिल्लो संशोधनमा $2द्वारा परिवर्तन गरि पुनः फर्काइएको।",
        "sessionfailure-title": "सत्र त्रुटी",
        "sessionfailure": "यस्तो लाग्दैछ कि तपाईंको लगइन सत्रसँग कुनै समस्या छ। सत्र अपहरणबाट बचाउन को लागि सावधानीको रूपमा तपाईंको यो क्रियाकलाप रद्द गरिएको छ। कृपया पछाडी जानुहोस र पृष्ठलाई पुनः लोड गर्नुहोस्, अनि फेरी प्रयास गर्नुहोला।",
-       "changecontentmodel-title-label": "पाना à¤¶à¥\80रà¥\8dषà¤\95",
+       "changecontentmodel-title-label": "पà¥\83षà¥\8dठ à¤¶à¥\80रà¥\8dषà¤\95:",
        "changecontentmodel-reason-label": "कारण:",
        "changecontentmodel-submit": "परिवर्तन गर्नुहोस्",
        "logentry-contentmodel-change-revertlink": "पहिलेको रुपमा फर्काउने",
        "undeletepagetext": "निम्नलिखित {{PLURAL:$1|पृष्ठ मेटिएकोछ तर पूरालेखभित्रै छ|$1 पृष्ठ मेटिएकाछन् तर पूरालेखभित्रै छन्}} र पुनर्स्थापित गर्न सकिन्छ।\nपूरालेखको समय-समयमा सफाई गर्न सकिन्छ।",
        "undelete-fieldset-title": "पुनरावलोकनहरू  पूर्वावस्थामा ल्याउनुहोस्",
        "undeleteextrahelp": "यस पृष्ठको पुरै इतिहास पूर्वरुपमा फर्काउनको लागि  छनोट सन्दुकहरूलाई नछानी '''''{{int:undeletebtn}}''''' मा क्लिक गर्नुहोस।\nअनुकुल पूर्वरुपमा फर्काउने कार्य गर्न छनौट चाहिएका संस्करणका सन्दुकहरूलाई छानेर '''''{{int:undeletebtn}}'''''मा क्लिक गर्नुहोस।",
-       "undeleterevisions": "$1 {{PLURAL:$1|सà¤\82शà¥\8bधन|सà¤\82शà¥\8bधनहरà¥\82}} à¤¸à¤\82à¤\97à¥\8dरहित",
+       "undeleterevisions": "$1 {{PLURAL:$1|सà¤\82शà¥\8bधन|सà¤\82शà¥\8bधनहरà¥\82}} à¤®à¥\87à¤\9fाà¤\87यà¥\8b",
        "undeletehistory": "यदि कुनै पृष्टलाई पुन: स्थापन गराउनु भयो भने सम्पूर्ण संस्करणहरू इतिहासमा पुन:स्थापन हुनेछन् ।\nयदि यसै नामबाट  नयाँ पृष्ठ निर्माण भैसकेको छ भने पुन: स्थापित संस्करणहरू पूर्व इतिहासको रुपमा स्थापित हुनेछन् ।",
        "undeleterevdel": "यदि यो माथिल्लो पृष्ठ बन्छ  या फाइल संस्करणहरू आंशिक मेटिएका छन् भने मेट्ने काम रद्द गरिने छैन।\nत्यस अवस्थामा तपाईंले छनौटमा अन्तिम मेटिएको नयाँ संस्करण नलुकाउनेमा चिनो लगाउनु पर्छ ।",
        "undeletehistorynoadmin": "यस पृष्ठ मेटिएको छ।\nमेटिनाको कारण निम्न जानकारीहरुमा खुलाइएको छ र मेटिनु अगिका योगदानकर्ताहरुको नाम पनि \nमेटिएका पृष्ठको पूरा पाठ प्रवन्धकहरुलाई मात्र उपलब्ध हुन्छ ।",
        "undelete-show-file-submit": "हो",
        "namespace": "नामस्थान:",
        "invert": "रोजाइ उल्टाउने",
-       "tooltip-invert": "à¤\9bानिà¤\8fà¤\95ा à¤¨à¥\87मसà¥\8dपà¥\87सहरà¥\82मा à¤°à¤¹à¥\87à¤\95ा à¤ªà¥\83षà¥\8dठहरà¥\82मा à¤\97रिà¤\8fà¤\95ा à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनहरà¥\82 à¤²à¥\81à¤\95ाà¤\89न à¤¯à¤¸à¤®à¤¾ à¤\9aिनà¥\8b à¤²à¤\97ाà¤\89नà¥\81हà¥\8bसà¥\8d  (र à¤¸à¤®à¥\8dबनà¥\8dधित à¤¨à¥\87मसà¥\8dपà¥\87स à¤¯à¤¦à¤¿ à¤\9bानिà¤\8fà¤\95ा à¤­à¤\8f)",
+       "tooltip-invert": "à¤\9bानिà¤\8fà¤\95ा à¤¨à¤¾à¤®à¤ªà¤¦à¤¹à¤°à¥\82मा à¤°à¤¹à¥\87à¤\95ा à¤ªà¥\83षà¥\8dठहरà¥\82मा à¤\97रिà¤\8fà¤\95ा à¤ªà¤°à¤¿à¤µà¤°à¥\8dतनहरà¥\82 à¤²à¥\81à¤\95ाà¤\89न à¤¯à¤¸à¤®à¤¾ à¤\9aिनà¥\8b à¤²à¤\97ाà¤\89नà¥\81हà¥\8bसà¥\8d  (र à¤\9bानिà¤\8fà¤\95ा à¤­à¤\8f à¤¸à¤®à¥\8dबनà¥\8dधित à¤¨à¤¾à¤®à¤ªà¤¦)",
        "tooltip-whatlinkshere-invert": "छानिएको नामस्थानको पृष्ठहरूसँग लिङ्कहरूलाई लुकाउनका लागि यस बाकसलाई चिन्हित गर्नुहोस",
-       "namespace_association": "समà¥\8dबनà¥\8dधित à¤¨à¥\87मसà¥\8dपà¥\87स",
-       "tooltip-namespace_association": "वारà¥\8dतालाप à¤¯à¤¾ à¤µà¤¿à¤·à¤¯ à¤¨à¥\87मसà¥\8dपà¥\87सहरà¥\81लाà¤\88 à¤¸à¤®à¥\8dवनà¥\8dधित à¤¨à¥\87मसà¥\8dपà¥\87सà¤\95à¥\8b à¤°à¥\81पमा à¤²à¤¿à¤¨à¤\95à¥\8b à¤²à¤¾à¤\97ि à¤¸à¤¨à¥\8dदà¥\81à¤\95मा à¤\9aिनà¥\8b à¤²à¤\97ाà¤\89नà¥\81हà¥\8bस।",
+       "namespace_association": "समà¥\8dबनà¥\8dधित à¤¨à¤¾à¤®à¤ªà¤¦",
+       "tooltip-namespace_association": "वारà¥\8dतालाप à¤¯à¤¾ à¤µà¤¿à¤·à¤¯ à¤¨à¤¾à¤®à¤ªà¤¦à¤¹à¤°à¥\82लाà¤\88 à¤¸à¤®à¥\8dबनà¥\8dधित à¤¨à¤¾à¤®à¤ªà¤¦à¤\95à¥\8b à¤°à¥\81पमा à¤²à¤¿à¤¨à¤\95à¥\8b à¤²à¤¾à¤\97ि à¤¸à¤¨à¥\8dदà¥\81à¤\95मा à¤\9aिनà¥\8b à¤²à¤\97ाà¤\89नà¥\81हà¥\8bसà¥\8d।",
        "blanknamespace": "(मुख्य)",
        "contributions": "{{GENDER:$1|प्रयोगकर्ता}}का योगदानहरू",
        "contributions-title": "$1को प्रयोगकर्ता योगदानहरू",
        "year": "वर्ष देखि( र पहिले):",
        "sp-contributions-blocklog": "रोकावट लग",
        "sp-contributions-suppresslog": "प्रयोगकर्ताको योगदानहरू दबाइएको छ ।",
-       "sp-contributions-deleted": "प्रयोगकर्ताका योगदानहरू मेटाइयो",
+       "sp-contributions-deleted": " {{GENDER:$1|प्रयोगकर्ता}}का योगदानहरू मेटाइयो",
        "sp-contributions-uploads": "उर्ध्वभरणहरू",
        "sp-contributions-logs": "लगहरू",
        "sp-contributions-talk": "वार्ता",
-       "sp-contributions-userrights": "प्रयोगकर्ता अधिकार व्यवस्थापन",
+       "sp-contributions-userrights": "{{GENDER:$1|प्रयोगकर्ता}} अधिकार व्यवस्थापन",
        "sp-contributions-blocked-notice": "यो प्रयोगकर्तालाई अहिले रोक लगाइएको छ।\nनवीनतम रोकाइ गरेको लग प्रविष्टि सन्दर्भको निम्ति तल दिएकोछ:",
        "sp-contributions-blocked-notice-anon": "यो IP ठेगानालाई अहिले रोक लगाइएको छ।\nनवीनतम रोकाइ गरेको लग प्रविष्टि सन्दर्भको निम्ति तल दिएकोछ:",
        "sp-contributions-search": "योगदानहरू खोज्नुहोस्",
        "cant-move-to-user-page": "तपाईंलाई पृष्ठहरू प्रयोगकर्ता पृष्ठमा सार्न अनुमती छैन (प्रयोगकर्ता सहपृष्ठहरूमा बाहेक)",
        "cant-move-category-page": "तपाईंलाई श्रेणीको पृष्ठहरू सार्ने अनुमति छैन ।",
        "cant-move-to-category-page": "कुनै श्रेणी पृष्ठमा सार्नको लागी तपाईँलाई अनुमति छैन ।",
-       "newtitle": "नयाँ शीर्षकमा :",
+       "newtitle": "नयाँ शीर्षक:",
        "move-watch": "यो पृष्ठ निगरानीमा राख्नुहोस्",
        "movepagebtn": "पृष्ठ सार्नुहोस्",
        "pagemovedsub": "सार्ने काम सफल भयो",
        "movenosubpage": "यस पृष्ठका उप पृष्ठहरू छैनन्।",
        "movereason": "कारण :",
        "revertmove": "पूर्ववत्",
-       "delete_and_move_text": "== मेटाउनु आवश्यक ==\nलक्ष्य गरिएको पृष्ठ  \"[[:$1]]\" पहिलादेखि छ\nके तपाईं यो त्यहाँ सार्न त्यसलाई मेट्न चाहनुहुन्छ?",
+       "delete_and_move_text": "लक्ष्य गरिएको पृष्ठ \"[[:$1]]\" पहिल्यै छ।\nके तपाईं यसलाई मेटाएर यस कदमको लागि बाटो खुला गर्न चाहनुहुन्छ?",
        "delete_and_move_confirm": "हो, पृष्ठ मेट्नुहोस्",
        "delete_and_move_reason": " \"[[$1]]\"बाट सार्नलाई बाटो खुलाउन मेटियो",
        "selfmove": "स्रोत तथा लक्ष्य गरिएको पृष्ठको शीर्षक एउटै भएकाले;\nयसैमाथि पृष्ठ सार्न मिल्दैन",
        "tooltip-pt-mycontris": "{{GENDER:|तपाईंका}} योगदानहरूको सूची",
        "tooltip-pt-login": "तपाईंलाई प्रवेस गर्न सुझाव दिइन्छ ; तर यो जरुरी भने छैन",
        "tooltip-pt-logout": "निर्गमन",
-       "tooltip-pt-createaccount": "तपाà¤\88à¤\82लाà¤\88 à¤\96ाता à¤¬à¤¨à¤¾à¤\89न à¤° à¤²à¤\97 à¤\87न à¤\97रà¥\8dन à¤¹à¤¾à¤®à¤¿ à¤ªà¥\8dरà¥\8bतà¥\8dसाहित à¤\97रà¥\8dà¤\9bà¥\8c; à¤¤à¤¥à¤¾à¤ªà¤¿, à¤¯à¥\8b à¤\85निवारà¥\8dय à¤­à¤¨à¥\87 à¤\9bà¥\88न ।",
+       "tooltip-pt-createaccount": "तपाà¤\88à¤\81लाà¤\88 à¤\96ाता à¤¬à¤¨à¤¾à¤\89न à¤° à¤ªà¥\8dरवà¥\87श à¤\97रà¥\8dन à¤¹à¤¾à¤®à¥\80 à¤ªà¥\8dरà¥\8bतà¥\8dसाहित à¤\97रà¥\8dà¤\9bà¥\8cà¤\82; à¤¤à¤¥à¤¾à¤ªà¤¿, à¤¯à¥\8b à¤\85निवारà¥\8dय à¤­à¤¨à¥\87 à¤\9bà¥\88न।",
        "tooltip-ca-talk": "सामग्री पृष्ठबारेमा छलफल",
        "tooltip-ca-edit": "यो पृष्ठ सम्पादन गर्ने",
        "tooltip-ca-addsection": "नयाँ खण्ड सुरु गर्नुहोस्",
        "tooltip-t-upload": "फाइल अपलोड गर्ने",
        "tooltip-t-specialpages": "सबै विशेष पृष्ठहरूको सूची",
        "tooltip-t-print": "यो पृष्ठको मुद्रण योग्य संस्करण",
-       "tooltip-t-permalink": "पà¥\83षà¥\8dठà¤\95à¥\8b à¤¯à¥\8b à¤ªà¥\81नरावलà¥\8bà¤\95नà¤\95à¥\8b à¤²à¤¾à¤\97ि à¤¸à¥\8dथाà¤\88 लिङ्क",
-       "tooltip-ca-nstab-main": "सामग्री पृष्ठ हेर्नुहोस",
+       "tooltip-t-permalink": "पà¥\83षà¥\8dठà¤\95à¥\8b à¤¯à¥\8b à¤ªà¥\81नरावलà¥\8bà¤\95नà¤\95à¥\8b à¤²à¤¾à¤\97ि à¤¸à¥\8dथायà¥\80 लिङ्क",
+       "tooltip-ca-nstab-main": "सामग्री पृष्ठ हेर्नुहोस",
        "tooltip-ca-nstab-user": "प्रयोगकर्ता पृष्ठ हेर्नुहोस्",
        "tooltip-ca-nstab-media": "मिडिया पृष्ठ हेर्नुहोस्",
        "tooltip-ca-nstab-special": "यो विशेष पृष्ठ हो, यो सम्पादन गर्न सकिदैन",
        "autoredircomment": "पृष्ठ[[$1]]मा पठाइएको",
        "autosumm-new": " $1 को साथमा पृष्ठ शृजना भयो",
        "autosumm-newblank": "खाली पृष्ठ तयार गर्ने",
-       "size-bytes": "$1 बाइटहरू",
+       "size-bytes": "$1 {{PLURAL:$1|बाइट|बाइटहरू}}",
        "size-kilobytes": "$1 किलोबाइटहरू",
        "size-megabytes": "$1 मेगाबाइटहरू",
        "size-gigabytes": "$1 गिगाबाइटहरू",
        "watchlistedit-raw-done": "तपाईंको निगरानी सूची अद्यावधिक गरिएको छ।",
        "watchlistedit-raw-added": "{{PLURAL:$1|१ शिर्षक|$1 शिर्षकरु}} थपियो:",
        "watchlistedit-raw-removed": "{{PLURAL:$1|१ शिर्षक|$1 शिर्षकरु}} हटाइयो:",
-       "watchlistedit-clear-title": "अवलोकन सूची खाली गरियो",
+       "watchlistedit-clear-title": "अवलोकनसूची खाली गर्नुहोस्",
        "watchlistedit-clear-legend": "अवलोकन सूची खाली गर्ने",
        "watchlistedit-clear-explain": "तपाईंको अवलोकन सूचीबाट सम्पूर्ण शिर्षकहरू मेटाइदै",
        "watchlistedit-clear-titles": "शीर्षकहरू :",
        "fileduplicatesearch-result-1": "फाइल\"$1\" को दुरुस्त नक्कलहरु छैनन् ।",
        "fileduplicatesearch-result-n": "फाइल\"$1\" को {{PLURAL:$2|1 दुरुस्त नक्कल|$2 दुरुस्त नक्कलहरु}} छन् ।",
        "fileduplicatesearch-noresults": "\"$1\" नामको फाइल पाइएन।",
-       "specialpages": "विशेष पृष्ठ",
+       "specialpages": "विशेष पृष्ठहरू",
        "specialpages-note-top": "आदर्श वाक्य",
        "specialpages-note-restricted": "* साधारण विशेष पृष्ठहरू।\n* <span class=\"mw-specialpagerestricted\">निषेधित विशेष पृष्ठहरू।</span>",
        "specialpages-group-maintenance": "मर्मत प्रतिवेदनहरू",
        "tags-actions-header": "कार्यहरु",
        "tags-active-yes": "हो",
        "tags-active-no": "हैन",
-       "tags-source-extension": "à¤\8fà¤\95à¥\8dसà¤\9fà¥\87नà¥\8dसनदà¥\8dवारा à¤ªà¤°à¤¿à¤­à¤¾à¤·à¤¿à¤¤ à¤\97रà¥\8dनà¥\87",
+       "tags-source-extension": "सफà¥\8dà¤\9fवà¥\87यरदà¥\8dवारा à¤ªà¤°à¤¿à¤­à¤¾à¤·à¤¿à¤¤",
        "tags-source-manual": "प्रयोगकर्ताहरू तथा बोटहरूबाट म्यानुअल्ली लागु गरिएको",
        "tags-source-none": "प्रयोगमा नरहेको",
        "tags-edit": "सम्पादन गर्नुहोस्",
        "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": "परिवरà¥\8dतनहरà¥\82 à¤¸à¤«à¤²à¤¤à¤¾ à¤ªà¥\82रà¥\8dवà¤\95 à¤²à¤¾à¤\97à¥\81 à¤­à¥\88सà¤\95à¥\8dयो",
+       "tags-edit-success": "परिवरà¥\8dतनहरà¥\82 à¤²à¤¾à¤\97à¥\81 à¤\97रियो",
        "tags-edit-failure": "यी परिवर्तनहरू लागु गर्न सकिएनः\n$1",
        "tags-edit-nooldid-title": "अवैध संशोधन लक्ष्य",
        "tags-edit-nooldid-text": "या त तपाईंले कुनै लक्षित संशोधनको विवरण दिनुभएको छैन जहाँ यस कार्यलाई सम्पन्न गर्नु पर्नेछ, या विवरण गरिएको संशोधन छंदै छैन।",
        "logentry-rights-autopromote": "$1 को प्रयोगकर्ता समूह स्वतः $4 बाट परिवर्तन गरेर $5 {{GENDER:$2|गरिएको}} थियो",
        "logentry-upload-upload": "$1 ले $3 {{GENDER:$2|अपलोड गरेका छन्}}",
        "logentry-upload-overwrite": "$1 ले $3 को नयाँ संस्करण {{GENDER:$2|अपलोड गरेका छन्}}",
-       "logentry-upload-revert": "$1 ले $3 {{GENDER:$2|अपलोड गरेका छन्}}",
+       "logentry-upload-revert": "$1ले $3लाई पुरानो संस्करणमा {{GENDER:$2|उल्टाउनुभयो}}",
        "log-name-managetags": "ट्याग व्यवस्थापन लग",
        "log-description-managetags": "यस पृष्ठमा ती प्रवन्धन कार्यहरूको सूची छ जुन [[Special:Tags|ट्यागहरू]]सँग सम्बन्धित छ। लगमा मात्रै ती क्रियाहरूको बयान गरिएको छ जुन मानवीय रूपले कुनै प्रवन्धकद्वारा पुरा गरिएको छ। ट्यागहरूलाई विकि सफ्टवेयरद्वारा बनउनु वा हटाउन सकिनेछ जसको प्रविष्टि लगमा हुनु आवश्यक छैन।",
        "logentry-managetags-create": "$1 ले ट्याग $4 {{GENDER:$2|तयार गरेको छ}}",
        "api-error-emptypage": "नयाँ तयार गर्दै, खाली पृष्ठ तयार गर्न अनुमति छैन ।",
        "api-error-publishfailed": "आन्तरिक समस्याः अस्थायी फाइल प्रकाशन गर्न सर्भर असफर भयो ।",
        "api-error-stashfailed": "आन्तरिक त्रुटि: अस्थाई फाइल राख्न सर्वर असफल भयो।",
-       "api-error-unknown-warning": "अज्ञात चेतावनी: \"$1\"",
+       "api-error-unknown-warning": "अज्ञात चेतावनी:\"$1\"।",
        "api-error-unknownerror": "अज्ञात त्रुटि: \"$1\".",
        "duration-seconds": "$1 {{PLURAL:$1|सेकेण्ड|सेकेण्डहरू}}",
        "duration-minutes": "$1 {{PLURAL:$1|मिनेट|मिनेटहरू}}",
        "special-characters-title-emdash": "इएम ड्यास",
        "special-characters-title-minus": "घटाउने चिन्ह",
        "mw-widgets-abandonedit": "के तपाई सम्पादन सङ्ग्रह नगरीकन सम्पादनबाट बाहिरिनेमा निश्चित हुनुहुन्छ?",
-       "mw-widgets-abandonedit-discard": "सम्पादन रद्द गर्नु",
-       "mw-widgets-abandonedit-keep": "समà¥\8dपादन à¤\9cारà¥\80 à¤°à¤¾à¤\96à¥\8dनà¥\87",
-       "mw-widgets-abandonedit-title": "निशà¥\8dà¤\9aित à¤¹à¥\81नà¥\81हà¥\81नà¥\8dà¤\9b ?",
+       "mw-widgets-abandonedit-discard": "सम्पादनहरू रद्द गर्नुहोस्",
+       "mw-widgets-abandonedit-keep": "समà¥\8dपादन à¤\9cारà¥\80 à¤°à¤¾à¤\96à¥\8dनà¥\81हà¥\8bसà¥\8d",
+       "mw-widgets-abandonedit-title": "à¤\95à¥\87 à¤¤à¤ªà¤¾à¤\88à¤\81 à¤ªà¤\95à¥\8dà¤\95ा à¤¹à¥\81नà¥\81हà¥\81नà¥\8dà¤\9b?",
        "mw-widgets-titleinput-description-new-page": "हालसम्म पृष्ठ उपलब्ध छैन्",
-       "mw-widgets-titleinput-description-redirect": "$1 à¤®à¤¾ à¤\9cानà¥\87",
+       "mw-widgets-titleinput-description-redirect": "$1 à¤®à¤¾ à¤ªà¥\81नरà¥\8dनिरà¥\8dदà¥\87श",
        "randomrootpage": "यादृच्छिक शीर्ष पृष्ठ",
        "log-action-filter-all": "सबै",
        "log-action-filter-block-block": "रोक्ने",
index eb7b6d5..bcd51af 100644 (file)
        "undo-norev": "De bewerking kon niet ongedaan gemaakt worden, omdat die niet bestaat of is verwijderd.",
        "undo-nochange": "De bewerking lijkt al ongedaan gemaakt te zijn.",
        "undo-summary": "Versie $1 van [[Special:Contributions/$2|$2]] ([[User talk:$2|overleg]]) ongedaan gemaakt",
+       "undo-summary-anon": "Versie $1 van [[Special:Contributions/$2|$2]] ongedaan gemaakt",
        "undo-summary-username-hidden": "Versie $1 door een verborgen gebruiker ongedaan gemaakt",
        "cantcreateaccount-text": "Registreren vanaf dit IP-adres ('''$1''') is geblokkeerd door [[User:$3|$3]].\n\nDe door $3 opgegeven reden is ''$2''",
        "cantcreateaccount-range-text": "Het aanmaken van gebruikers vanaf IP-adressen in de range <strong>$1</strong> is niet mogelijk doordat dit is ingesteld door [[User:$3|$3]]. Uw IP-adres $4 bevindt zich in deze range.\n\nDe reden voor de blokkade is <em>$2</em>",
        "alreadyrolled": "Het is niet mogelijk om de bewerking van de pagina [[:$1]] door [[User:$2|$2]] ([[User talk:$2|overleg]]{{int:pipe-separator}}[[Special:Contributions/$2|bijdragen]]) ongedaan te maken.\nIemand anders heeft deze pagina al bewerkt of hersteld naar een eerdere versie.\n\nDe meest recente bewerking is gemaakt door [[User:$3|$3]] ([[User talk:$3|overleg]]{{int:pipe-separator}}[[Special:Contributions/$3|bijdragen]]).",
        "editcomment": "De bewerkingssamenvatting was: <em>$1</em>.",
        "revertpage": "Wijzigingen door [[Special:Contributions/$2|$2]] ([[User talk:$2|Overleg]]) hersteld tot de laatste versie door [[User:$1|$1]]",
+       "revertpage-anon": "Wijzigingen door [[Special:Contributions/$2|$2]] teruggedraaid naar de laatste versie door [[User:$1|$1]]",
        "revertpage-nouser": "Wijzigingen door een verborgen gebruiker teruggedraaid naar de laatste versie door {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Wijzigingen door {{GENDER:$3|$1}} ongedaan gemaakt;\nlaatste versie van {{GENDER:$4|$2}} hersteld.",
        "sessionfailure-title": "Sessiefout",
        "ipblocklist-legend": "Een geblokkeerde gebruiker zoeken",
        "blocklist-userblocks": "Geblokkeerde accounts verbergen",
        "blocklist-tempblocks": "Tijdelijke blokkades verbergen",
+       "blocklist-indefblocks": "Verberg blokkades met een oneindige loopduur",
        "blocklist-addressblocks": "Blokkades van één IP-adres verbergen",
        "blocklist-type": "Soort:",
        "blocklist-type-opt-all": "Alle",
index 75e75f4..f474a8b 100644 (file)
        "tog-usenewrc": "ߞߙߎ ߡߊߝߊ߬ߟߋ߲߬ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߞߐ߯ߟߕߊ ߟߎ߬ ߣߌ߫ ߜߋ߬ߟߎ߲߬ߠߌ߲߬ ߛߙߍߘߍ ߘߐ߫.",
        "tog-numberheadings": "ߕߍ߰ߟߌ ߡߐ߬ߟߐ߲ ߠߎ߬ ߝߙߍߕߍ߫ ߞߍ߲ߖߘߍߡߊߓߟߏߡߊ߬",
        "tog-editondblclick": "ߞߏߜߍ ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫ ߛߐ߲߬ߞߌ߲߬ߠߌ߲߬ߞߏ ߝߌ߬ߟߊ߬ ߟߊ߫",
+       "tog-editsectiononrightclick": "ߕߍߕߎ߲߮ ߞߌߣߌ߲ߝߍ߫ ߡߊߦߟߍߡߊ߲ߠߌ߲ ߕߍ߫ ߕߍߕߎ߲߮ ߞߎ߲߬ߕߐ߮ ߟߊ߫.",
        "tog-watchcreations": "ߒ ߠߊ߫ ߞߐߜߍ߫ ߛߌ߲ߘߌ߫ ߣߍ߲ ߠߎ߬ ߣߌ߫ ߞߐߕߐ߯ ߟߊߦߟߍ߬ߣߍ߲ ߠߎ߬ ߓߌ߬ߟߊ߬ ߒ ߠߊ߫ ߜߋ߬ߟߎ߬ߠߌ߲߬ ߛߙߍߘߍ ߘߐ߫.",
        "tog-watchdefault": "ߒ ߠߊ߫ ߞߐߜߍ߫ ߣߌ߫ ߞߐߕߐ߯ ߡߊߦߟߍ߬ߡߊ߲߬ߣߍ߲ ߠߎ߬ ߓߌ߬ߟߊ߬ ߒ ߠߊ߫ ߜߋ߬ߟߎ߬ߠߌ߲߬ ߛߙߍߘߍ ߘߐ߫.",
        "tog-watchmoves": "ߒ ߠߊ߫ ߞߐߜߍ ߣߌ߫ ߞߐߕߐ߯ ߟߊߕߐߣߍ߲ ߠߎ߬ ߓߌ߬ߟߊ߬ ߒ ߠߊ߫ ߜߋ߬ߟߎ߬ߠߌ߲߬ ߛߙߍߘߍ ߘߐ߫.",
        "tog-watchdeletion": "ߒ ߠߊ߫ ߞߐߜߍ ߣߌ߫ ߞߐߕߐ߯ ߖߏ߬ߛߌ߬ߣߍ߲ ߠߎ߬ ߓߌ߬ߟߊ߬ ߒ ߠߊ߫ ߜߋ߬ߟߎ߬ߠߌ߲߬ ߛߙߍߘߍ ߘߐ߫.",
        "tog-watchuploads": "ߒ ߠߊ߫ ߞߐߕߐ߯ ߟߊߦߟߍ߬ߣߍ߲ ߠߎ߬ ߓߌ߬ߟߊ߬ ߒ ߠߊ߫ ߜߋ߬ߟߎ߬ߠߌ߲߬ ߛߙߍߘߍ ߘߐ߫.",
+       "tog-watchrollback": "ߞߐߜߍ ߟߎ߬ ߟߊߘߏ߲߬ ߒ ߠߊ߫ ߦߟߌߡߊߛߙߋ ߟߛߊ߬ߦߌ߲߬ߣߍ߲߬ ߣߐ߬ߡߊߢߌ߲߬ߧߊ߬ߣߍ߲ ߠߎ߬ ߘߐ߫.",
        "tog-minordefault": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߘߋ߬ߣߍ߲ ߠߎ߬ ߣߐ߬ߣߐ߬ ߓߐߛߎ߲ ߘߌ߫",
        "tog-previewontop": "ߢߍߦߋߟߌ ߦߌ߬ߘߊ߬ ߡߊ߰ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߞߏ߲ߘߏ ߢߍ߫.",
        "tog-previewonfirst": "ߢߍߦߋߟߌ ߦߌ߬ߘߊ߬ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߝߟߐ ߘߐ߫.",
@@ -57,6 +59,8 @@
        "underline-default": "ߝߊ߬ߘߌ ߥߟߊ߫ ߛߏ߲߯ߓߊߟߊ߲ ߠߊ߫ ߝߍ߭",
        "editfont-style": "ߕߌ߲߬ߞߎߘߎ߲ ߛߓߍߛߎ߲ ߛߎ߯ߦߊ ߢߊߓߐ߫:",
        "editfont-monospace": "ߞߣߍߙߋ߲ ߛߓߍߛߎ߲",
+       "editfont-sansserif": "ߛߊ߲-ߛߋ߬ߙߌߝ ߞߟߏߜߍ",
+       "editfont-serif": "ߛߋ߬ߙߌߝ ߞߟߏߜߍ",
        "sunday": "ߞߊ߯ߙߌߟߏ߲",
        "monday": "ߞߐ߬ߓߊ߬ߟߏ߲",
        "tuesday": "ߞߐ߬ߟߏ߲",
        "privacy": "ߘߎ߲߬ߘߎ߬ߡߊ߬ ߓߘߍߓߘߍߟߌ",
        "privacypage": "Project:ߘߎ߲߬ߘߎ߬ߡߊ߬ ߓߘߍ߬ߓߘߍ߬ߟߌ",
        "badaccess": "ߟߊ߬ߘߌ߬ߢߍ߬ߟߌ ߝߎ߬ߕߎ߲߬ߕߌ",
+       "badaccess-group0": "ߌ ߣߊ߬ ߞߏ ߡߍ߲ ߡߊߢߌ߬ߣߌ߲߬ߞߊ߬ ߟߴߏ߬ ߘߌ߫߸ ߌ ߟߊߘߌ߬ߢߍ߬ߣߍ߲߬ ߕߍ߫ ߞߵߏ߬ ߞߍ߫.",
        "badaccess-groups": "ߌ ߣߊ߬ ߞߍߢߊ ߡߍ߲ ߡߊߢߌ߬ߣߌ߲߬ߞߊ߬ ߟߊ߫ ߣߌ߲߬߸ ߏ߬ ߟߊߓߊ߯ߙߊ ߡߊߓߍ߲߬ߣߍ߲߫ ߠߋ߫ ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߡߍ߲ ߠߎ߬ ߦߋ߫ {{PLURAL:$2|ߞߙߎ ߘߐ߫|ߞߙߎ ߘߏ߫ ߘߐ߫}}: $1.",
        "versionrequired": "ߡߊߘߌߦߊ߫-ߥߞߌ߫ ߓߊߦߟߍߡߊ߲ߠߌ߲ $1 ߞߊ߬ߣߌ߲߬ ߣߍ߲߫",
        "versionrequiredtext": "ߡߊߘߌߦߊ߫-ߥߞߌ߫ ߘߟߊߡߌߘߊߟߌ $1 ߞߊ߬ߣߌ߲߬ ߣߍ߲߫ ߞߊ߬ ߞߐߜߍ ߣߌ߲߬ ߠߊߓߊ߯ߙߊ߫.\n[[Special:Version|version page]] ߦߋ߫.",
        "nstab-category": "ߦߌߟߡߊ",
        "mainpage-nstab": "ߓߏ߬ߟߏ߲߬ߘߊ",
        "nosuchaction": "ߞߍߟߌ߫ ߛߎ߮ ߏ߬ ߕߴߦߋ߲߬",
+       "nosuchactiontext": "ߞߏ ߡߍ߲ ߞߙߍߞߙߍߣߍ߲ ߦߋ߫ URL ߓߟߏ߫߸ ߏ߬ ߓߍ߲߬ ߣߍ߲߬ ߕߍ߫.\nߌ ߝߟߌ߬ߣߍ߲߫ ߘߌ߫ ߞߍ߫ URL ߛߓߍ߫ ߕߎߡߊ ߟߊ߫߸ ߥߟߊ߫ ߛߘߌ߬ߜߋ߲ ߓߍ߲߬ߓߊߟߌ ߟߋ߬ ߟߊߓߊ߬ߕߏ߬ߣߍ߲߬ ߦߵߌ ߓߟߏ߫.\nߕߎ߬ߡߊ߬ߘߐ߫ ߏ߬ ߝߣߊ߫ ߘߴߊ߬ ߦߌ߬ߘߊ߬ ߞߏ߫ ߝߏ߬ߘߏ ߦߋ߫ ߛߎ߲ߝߘߍ߫ ߟߊߓߊ߯ߙߊߣߍ߲ ߘߐ߫  {{SITENAME}} ߓߟߏ߫.",
        "nosuchspecialpage": "ߘߐߜߍ߫ ߓߟߏߡߊߞߊ߬ߣߍ߲߬ ߛߎ߮ ߏ߬ ߝߋ߲߫ ߕߍ߫ ߦߊ߲߬",
        "nospecialpagetext": "<strong>ߊߟߎ߫ ߓߘߊ߫ ߞߐߜߍ߫ ߓߟߏߡߊߞߊ߬ߣߍ߲ ߘߏ߫ ߢߌߣߌ߲߫ ߡߍ߲ ߕߺߴߦߋ߲߬.</strong>\nߞߐߜߍ߫ ߓߟߏߡߊߞߊ߬ߣߍ߲߫ ߓߘߍ߬ߡߊ ߟߎ߬ ߛߙߍߘߍ ߦߋ߫ ߢߌ߲߬ ߠߋ߫ ߞߊ߲߬ [[Special:SpecialPages|{{int:specialpages}}]].",
        "error": "ߝߎ߬ߕߎ߲߬ߕߌ",
        "databaseerror": "ߓߟߏߡߟߊ ߟߎ߬ ߝߊ߲ ߝߎ߬ߕߎ߲߬ߕߌ",
+       "databaseerror-text": "ߓߟߏߡߟߊߝߊ߲ ߢߌ߬ߣߌ߲߬ߞߊ߬ߟߌ ߝߎ߬ߕߎ߲߬ߕߌ ߘߏ߫ ߓߘߴߊ߬ ߓߌ߬ߟߵߊ߬ ߘߐ߫.\nߏ߬ ߦߴߊ߬ ߦߌ߬ߘߊ߬ ߟߊ߫ ߟߋ߬ ߞߏ߫ ߝߏ߬ߘߏ ߦߋ߫ ߛߎ߲ߝߘߍ ߘߐ߫.",
        "databaseerror-textcl": "ߓߟߏߡߟߊߝߊ߲ ߢߌ߬ߣߌ߲߬ߞߊ߬ߟߌ ߝߎ߬ߕߎ߲߬ߕߌ ߘߏ߫ ߓߘߊ߫ ߓߌ߬ߟߵߊ߬ ߘߐ߫.",
        "databaseerror-query": "ߢߌ߬ߣߌ߲߬ߞߊ߬ߟߌ $1",
        "databaseerror-function": "ߗߋߘߊ $1",
        "databaseerror-error": "ߝߎ߬ߕߎ߲߬ߕߌ: $1",
+       "laggedslavemode": "<strong>ߖߊ߲߬ߓߌ߬ߟߊ߬ߟߌ</strong> ߟߏ߲ߘߐߦߊߟߌ߫ ߞߎߘߊ߫ ߛߌ߫ ߕߍ߫ ߞߐߜߍ ߘߐ߫.",
        "readonly": "ߓߟߏߡߟߊ ߝߊ߲ ߛߐ߰ߣߍ߲߫",
+       "enterlockreason": "ߛߐ߰ߟߌ ߞߎ߲߭ ߠߊߘߏ߲߬߸ ߞߵߏ߬ ߟߊ߫ ߛߐ߰ߟߌ ߓߊ߲߫ ߕߎߡߊ߫ ߖߊ߬ߕߋߡߌ߬ߘߊ߬ߣߍ߲ ߞߊ߲߬.",
        "missingarticle-rev": "(ߡߛߊ߬ߦߌ߲߬ߠߌ߲#:$1)",
        "missingarticle-diff": "(Diff: $1, $2)",
        "readonly_lag": "ߓߟߏߡߟߊ ߝߊ߲ ߓߘߊ߫ ߛߐ߰ ߞߍߒߖߘߍߦߋ߫ ߓߟߏߡߊ߬߸ ߞߊ߬ߦߌ߯ ߖߐ߲߬ ߓߟߏߡߟߊ ߝߊ߲ ߡߊߛߐߓߊ߮ ߡߌ߬ߣߊ߬ ߘߊ߫ ߞߙߊ߬ߡߐ߮ ߓߟߏ߫.",
        "editpage-cannot-use-custom-model": "ߞߐߜߍ ߣߌ߲߬ ߞߣߐߘߐ ߛߎ߮ߦߊ ߕߍߣߊ߬ ߛߐ߲߬ ߠߊ߫ ߡߊߦߟߍ߬ߡߊ߲߫ ߠߊ߫.",
        "templatesused": "{{PLURAL:$1|ߞߙߊߞߏ|ߞߙߊߞߏ ߟߎ߫}} ߟߎ߫ ߟߊߓߊ߯ߙߊ߫ ߘߊ߫ ߞߐߜߍ ߣߌ߲߬ ߘߐ߫",
        "templatesusedpreview": "{{PLURAL:$1|ߞߙߊߞߏ|ߞߙߊߞߏ ߟߎ߬}} ߟߋ߬ ߟߊߓߊ߯ߙߊ߫ ߣߍ߲߫ ߢߍߦߋߟߌ ߣߌ߲߬ ߘߐ߫",
+       "templatesusedsection": "{{PLURAL:$1|ߞߙߊߞߏ|ߞߙߊߞߏ ߟߎ߬}} ߟߋ߬ ߟߊߓߊ߯ߙߊ߫ ߣߍ߲߫ ߕߍߕߍ߮ ߣߌ߲߬ ߘߐ߫:",
        "template-protected": "(ߊ߬ ߡߊߞߊ߲ߞߊ߲ߣߍ߲߫ ߠߋ߬)",
        "template-semiprotected": "(ߟߊ߬ߞߊ߲߬ߘߊ߬ߟߌ-ߝߊ߲߬ߞߋ߬ߟߋ߲߬ߡߊ)",
        "hiddencategories": "ߞߐߜߍ ߣߌ߲߬ ߦߋ߫ ߢߌ߲߬ ߠߎ߫ ߛߌ߲߬ߝߏ߲ ߠߋ߬ ߘߌ߫{{PLURAL:$1|}}",
+       "nocreatetext": "{{SITENAME}} ߓߘߴߊ߬ ߛߋߞߏߦߊ ߟߊߞߎ߲߬ߛߌ߲߫ ߞߊ߬ ߞߐߜߍ߫ ߞߎߘߊ߫ ߟߊߘߊ߲߫.\nߌ ߘߌ߫ ߛߴߌ ߞߐߛߊ߬ߦߌ߬ ߟߊ߫ ߞߊ߬ ߛߋ߲߬ߠߊ߬ ߞߐߜߍ ߡߊߦߟߍ߬ߡߊ߲߫ ߸ ߥߟߊ߫  [[Special:UserLogin|log in or create an account]].",
        "nocreate-loggedin": "ߞߐߜߍ߫ ߞߎߘߊ߫ ߛߌ߲ߘߌ߫ ߞߏ ߟߊߘߌ߬ߢߍ߬ߣߍ߲߬ ߕߴߌ ߦߋ߫.",
+       "sectioneditnotsupported-title": "ߘߌ߬ߢߍ߬ ߞߍߣߍ߲߫ ߕߍ߫ ߕߍߕߍ߮ ߡߊߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߊ߬.",
        "sectioneditnotsupported-text": "ߛߌ߰ߘߊ ߡߊߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߠߊߘߤߊ߬ߣߍ߲߬ ߕߍ߫ ߞߐߜߍ ߣߌ߲߬ ߠߊ߫ ߕߊ߲߬.",
+       "modeleditnotsupported-title": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߟߊߘߌ߬ߢߍ߬ߣߍ߲߬ ߕߍ߫",
+       "modeleditnotsupported-text": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߟߊߘߌ߬ߢߍ߬ߣߍ߲߬ ߕߍ߫ ߞߣߐߘߐ ߛߎ߮ߦߊ $1 ߦߋ߫.",
        "permissionserrors": "ߝߌ߬ߟߌ߫ ߘߌ߬ߢߍ߬ߒߧߋ",
        "permissionserrorstext": "ߌ ߟߊߘߌ߬ߢߍ߬ߣߍ߲߬ ߕߍ߫ ߞߵߏ߬ ߞߍ߫߸ ߣߌ߲߬ ߠߊ߫ {{PLURAL:$1|ߛߊߓߎ|ߛߊߓߎ ߟߎ߬}}:",
        "permissionserrorstext-withaction": "ߟߊ߬ߘߌ߬ߢߍ߬ߟߌ߬ ߛߌ߫ ߕߴߌ ߦߋ߫ ߞߊ߬ $2߸ {{PLURAL:$1|ߞߏߛߐ߲߬|ߟߎ߬ ߞߏߛߐ߲߬}}",
        "contentmodelediterror": "ߌ ߕߍߣߊ߬ ߛߋ߫ ߟߊ߫ ߛߌ߰ߘߊ ߣߌ߲߬ ߡߊߦߟߍ߬ߡߊ߲߬ ߠߊ߫߸ ߓߊߏ߬ ߞߣߐߘߐ ߛߎ߯ߦߊ ߦߋ߫ <code>$1</code> ߟߋ߬ ߘߌ߫߸ ߡߍ߲ ߦߋ߫ ߕߋ߲߬ߕߋ߲߬ ߞߣߐߘߐ ߛߎ߯ߦߊ ߝߘߏ߬ ߟߊ߫ ߞߐߜߍ <code>$2</code> ߘߐ߫.",
        "recreate-moveddeleted-warn": "<strong>ߌ ߖߊ߲߬ߕߏ߫: ߌ ߦߋ߫ ߞߐߜߍ ߘߏ߫ ߟߋ߬ ߟߊߘߊ߲߫ ߞߏ ߘߐ߫ ߣߌ߲߬߸ ߡߍ߲ ߖߏ߬ߛߌ߬ߣߍ߲߬ ߡߎߣߎ߲߬.</strong> \nߌ ߓߛߌ߬ߞߌ߬ ߕߐ߫ ߟߋ߬ ߛߍ߲߸ ߣߴߌ ߘߌ߫ ߛߋ߫ ߞߐߜߍ ߣߌ߲߬ ߡߊߦߟߍ߬ߡߊ߲ ߘߊߓߊ߲߫ ߠߊ߫. \nߞߐߜߍ ߣߌ߲߬ ߦߟߌߣߐ ߖߏ߬ߛߌ߬ߣߍ߲ ߣߴߊ߬ ߛߋ߲߬ߓߐ߬ߣߍ߲ ߠߎ߬ ߡߊߘߊ߲ߣߍ߲߫ ߦߊ߲߬ ߠߋ ߟߊ߬ߣߐ߰ߦߊ߬ߟߌ ߘߌ߫:",
        "moveddeleted-notice": "ߞߐߜߍ ߣߌ߲߬ ߓߘߊ߫ ߖߏ߬ߛߌ߬.\nߖߏ߬ߛߌ߬ߟߌ߸ ߟߊ߬ߞߊ߲߬ߘߊ߬ߟߌ߸ ߊ߬ ߣߌ߫ ߞߐߜߍ ߛߓߍߟߌ ߟߎ߬ ߛߋ߲߬ߓߐ߸ ߏ߬ ߟߎ߫ ߓߍ߯ ߡߊߛߐߣߍ߲߫ ߦߋ߫ ߘߎ߰ߟߊ ߘߐ߫.",
+       "moveddeleted-notice-recent": "ߤߊߞߍ߬ߕߏ߫߸ ߞߐߜߍ ߣߌ߲߬ ߓߊ߲߫ ߛߊ߲߮ ߠߋ߬ ߦߋ߫ ߖߏ߬ߛߌ߬ ߟߊ߫ (ߕߎ߬ߡߊ߬ߙߋ߲߫ ߂߄ ߕߊ߬ߡߌ߲߬ߣߍ߲) ߣߌ߲߬ ߞߘߐ߫.\nߞߐߜߍ ߖߏ߰ߛߌ߬ߟߌ߸ ߟߊ߬ߞߊ߲߬ߘߊ߬ߟߌ߸ ߊ߬ ߣߌ߫ ߘߊ߲ߖߐ ߛߋ߲߬ߓߐ ߓߍ߯ ߡߊߛߐߣߍ߲߫ ߦߋ߫ ߘߎ߰ߟߊ ߘߐ߫ ߦߟߌߡߊߛߙߋ߫ ߞߏ ߘߐ߫.",
        "log-fulllog": "ߘߎ߲ߛߓߍ ߘߝߊߣߍ߲ ߦߋ߫",
+       "edit-hook-aborted": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߓߘߊ߫ ߘߐߛߊ߬ ߛߏ߲߭ߓߊ߬ߟߌ ߓߟߏ߫. \nߊ߬ ߘߏ߲߬ ߡߊ߫ ߘߊ߲߬ߕߍ߰ߟߍ߬ ߛߌ߫ ߞߍ߫.",
+       "edit-gone-missing": "ߞߐߜߍ ߕߍ߫ ߛߐ߲߬ ߟߏ߲ߘߐߦߊ߫ ߟߊ߫.\nߊ߬ ߦߌ߬ߘߊ߬ߣߍ߲߬ ߦߋ߫ ߞߴߊ߬ ߓߘߊ߫ ߖߏ߰ߛߌ߬.",
        "edit-conflict": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߝߐߢߐ߲߯ߞߐ.",
        "edit-no-change": "ߌ ߟߊ߫ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߕߎ߲߬ ߓߘߊ߫ ߡߊߓߌ߬ߟߊ߬߸ ߓߊߏ߬ ߡߝߊ߬ߟߋ߲߬ߠߌ߲߬ ߛߌ߫ ߕߎ߲߬ ߡߊ߫ ߞߍ߫ ߛߓߍߟߌ ߘߐ߫.",
        "postedit-confirmation-created": "ߞߐߜߍ ߓߘߊ߫ ߓߊ߲߫ ߛߌ߲ߘߌ߫ ߟߊ߫.",
        "right-minoredit": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߣߐ߬ߣߐ߬ ߡߌ߬ߛߍ߬ߡߊ߲ ߘߌ߫",
        "right-move": "ߞߐߜߍ ߟߎ߬ ߛߋ߲߬ߓߐ߫",
        "right-move-subpages": "ߞߐߜߍ ߛߋ߲߬ߓߐ߫ ߊ߬ߟߎ߬ ߟߊ߫ ߞߐߜߍߙߋ߲ ߠߎ߬ ߘߐ߫",
+       "right-move-rootuserpages": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ߫ ߟߌ߯ߟߌ߲ߖߌ߰ߣߍ߲ ߞߐߜߍ ߛߋ߲߬ߓߐ߫",
        "right-move-categorypages": "ߦߌߟߡߊ߫ ߞߐߜߍ ߟߎ߬ ߛߋ߲߬ߓߐ߫",
        "right-movefile": "ߞߐߕߐ߮ ߟߎ߬ ߛߋ߲߬ߓߐ߫",
        "right-upload": "ߞߐߕߐ߮ ߟߎ߬ ߟߊߦߟߍ߬",
        "right-sendemail": "ߢߎߡߍߙߋ߲ ߗߋ߫ ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߘߏ ߟߎ߬ ߡߊ߬",
        "grant-generic": "\"$1\" ߞߌߣߌ߲߫ ߝߍ߫ ߝߎߝߎ",
        "grant-group-page-interaction": "ߞߐߜߍ ߟߎ߬ ߟߊ߫ ߞߏߢߐ߲߯ߦߊ",
+       "grant-group-watchlist-interaction": "ߌ ߟߊ߫ ߦߟߌߡߊߛߙߋ ߞߏߢߐ߲߯ߦߊ",
        "grant-group-email": "ߢߎߡߍߙߋ߲ ߗߋ߫",
+       "grant-group-customization": "ߘߎ߲߬ߘߎ߬ߡߦߊ߬ߟߌ ߣߌ߫ ߦߟߌߡߊߛߙߋ",
        "grant-blockusers": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߟߎ߬ ߓߊ߬ߟߌ ߣߴߊ߬ߟߎ߬ ߓߊ߬ߟߌ߬ߣߍ߲ ߓߐߟߌ",
        "grant-createaccount": "ߖߊ߬ߕߋ߬ߘߊ ߘߏ߫ ߛߌ߲ߘߌ߫",
        "grant-createeditmovepage": "ߞߐߜߍ ߛߌ߲ߘߌ߫߸ ߡߊߦߟߍ߬ߡߊ߲߫߸ ߊ߬ ߣߌ߫ ߞߵߊ߬ ߛߋ߲߬ߓߐ߫",
        "grant-editpage": "ߞߐߜߍ߫ ߓߍߓߊ߮ ߡߊߦߟߍ߬ߡߊ߲߫",
        "grant-editprotected": "ߞߐߜߍ߫ ߟߊߞߊ߲ߘߊߣߍ߲ ߡߊߦߟߍ߬ߡߊ߲߫",
        "grant-highvolume": "ߢߊ߲ߞߊ߲-ߛߊ߲ߘߐߕߊ ߡߊߦߟߍߡߊ߲ ߦߴߌ ߘߐ߫",
+       "grant-oversight": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߢߡߊߘߏ߲߰ ߊ߬ ߣߌ߫ ߞߊ߬ ߟߢߊ߬ߟߌ ߟߎ߬ ߖߏ߬ߛߌ߬.",
        "grant-patrol": "ߞߐߜߍ ߟߎ߬ ߓߍ߬ߙߍ߲߬ߓߍ߬ߙߍ߲߬ߠߌ߲ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲",
        "grant-privateinfo": "ߘߎ߲߬ߘߎ߬ߡߊ߬ ߞߌߓߊߙߏߦߊ ߟߊߛߐ߬ߘߐ߲߬",
        "grant-protect": "ߞߐߜߍ ߟߎ߬ ߟߊߞߊ߲ߘߊ߫ ߊ߬ ߣߌ߫ ߞߵߊ߬ߟߎ߬ ߟߊߞߊ߲ߘߊߣߍ߲ ߓߐ߫",
        "action-writeapi": "ߛߓߍߟߌ API ߟߊߓߊ߯ߙߊ߫",
        "action-delete": "ߞߐߜߍ ߣߌ߲߬ ߖߏ߰ߛߌ߬",
        "action-deleterevision": "ߟߢߊ߬ߟߌ ߟߎ߬ ߖߏ߬ߛߌ߬",
+       "action-deletelogentry": "ߘߊ߲ߖߐ ߡߎ߰ߡߍ ߖߏ߬ߛߌ߬",
        "action-deletedhistory": "ߞߐߜߍ ߟߎ߬ ߖߏ߰ߛߌ߬ߟߌ ߘߐ߬ߝߐ ߦߋ߫",
        "action-deletedtext": "ߟߢߊ߬ߟߌ ߖߏ߰ߛߌ߬ߣߍ߲ ߠߎ߬ ߛߓߍߟߌ ߦߋ߫.",
        "action-browsearchive": "ߞߐߜߍ߬ ߖߏ߰ߛߌ߬ߣߍ߲ ߠߎ߬ ߢߌߣߌ߲߫",
        "action-undelete": "ߞߐߜߍ ߖߏ߰ߛߌ߬ߓߊߟߌ ߟߎ߬",
+       "action-suppressrevision": "ߟߢߊ߬ߟߌ߬ ߢߡߊߘߏ߲߰ߣߍ߲ ߠߎ߬ ߦߋ߫ ߊ߬ ߣߌ߫ ߞߵߊ߬ߟߎ߬ ߟߊߞߎߣߎ߲߫.",
        "action-suppressionlog": "ߘߎ߲߬ߘߎ߬ߡߊ߬ ߘߎ߲ߛߓߍ ߣߌ߲߬ ߦߋ߫",
        "action-block": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߣߌ߲߬ ߓߊ߬ߟߌ߬ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߊ߬",
        "action-protect": "ߞߐߜߍ ߣߌ߲߬ ߟߊ߬ߞߊ߲߬ߘߊ߬ߟߌ߬ ߞߛߊߞߊ ߡߊߝߊ߬ߟߋ߲߬",
+       "action-rollback": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߞߐߟߕߊ ߟߊ߫ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߟߊߞߐߛߊ߬ߦߌ߬ ߖߏߣߊߖߏߣߊ߫߹ ߡߍ߲ ߞߊ߬ ߞߐߜߍ߫ ߞߙߍߞߙߍߣߍ߲ ߡߊߦߟߍ߬ߡߊ߲߫.",
        "action-import": "ߞߐߜߍ ߟߎ߬ ߟߊߛߣߍ߫ ߞߊ߬ ߓߐ߫ ߥߞߌ ߕߐ߭ ߟߎ߬ ߘߐ߫",
        "action-importupload": "ߞߐߜߍ ߟߎ߬ ߟߊߛߣߍ߫ ߞߊ߬ ߓߐ߫ ߞߐߕߐ߯ ߟߊߦߟߍ߬ߣߍ߲ ߠߎ߬ ߘߐ߫",
        "action-patrol": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߘߏ ߟߎ߬ ߟߊ߫ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߠߎ߬ ߣߐ߬ߣߐ߬ ߓߍ߬ߙߍ߲߬ߓߍ߬ߙߍ߲߬ߣߍ߲ ߘߌ߫",
        "action-managechangetags": "ߘߎ߲ߛߓߍ ߟߎ߬ ߛߌ߲ߘߟߌ ߣߴߊ߬ߟߎ߬ ߓߐߒߠߊߟߌ",
        "action-applychangetags": "ߘߎ߲ߛߓߍ ߟߎ߬ ߟߊߓߊ߯ߙߊ߫ ߌ ߟߊ߫ ߡߝߊ߬ߟߋ߲߬ߠߌ߲ ߠߎ߬ ߞߊ߲߬",
        "action-deletechangetags": "ߘߎ߲ߛߓߍ ߟߎ߬ ߖߏ߬ߛߌ߬ ߞߊ߬ ߓߐ߫ ߓߟߏߡߟߊ ߝߊ߲ ߞߊ߲߬",
+       "action-purge": "ߞߐߜߍ ߣߌ߲߬ ߛߊߣߌ߲ߧߊ߫",
+       "action-apihighlimits": "API ߡߊߢߌߣߌ߲ߣߍ߲ ߛߊ߲ߘߐߕߊ ߟߊߓߊ߯ߙߊ߫",
+       "action-bigdelete": "ߞߐߜߍ߫ ߘߝߐ߬ ߓߟߋ߬ߓߟߋ߬ߡߊ ߟߎ߬ ߖߏ߰ߛߌ߬",
+       "action-blockemail": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߓߊ߬ߟߌ߬ ߢߎߡߍߙߋ߲ ߗߋߟߌ ߡߊ߬",
+       "action-editprotected": "ߞߐߜߍ ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫ ߡߍ߲ ߠߎ߬ ߟߊߞߊ߲ߘߊߣߍ߲߫ ߦߋ߫ \"{{int:protect-level-sysop}}\" ߓߟߏ߫.",
+       "action-editsemiprotected": "ߞߐߜߍ ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫ ߡߍ߲ ߠߎ߬ ߟߊߞߊ߲ߘߊߣߍ߲߫ ߦߋ߫  \"{{int:protect-level-autoconfirmed}}\"",
+       "action-editinterface": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߟߊ߫ ߢߐ߲߯ߕߍߞߣߍ ߡߊߦߟߍ߬ߡߊ߲߫",
        "action-editusercss": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߘߏ ߟߎ߬ CSS ߟߊ߬ߓߊ߰ߙߊ߬ߟߌ߬ ߞߐߕߐ߮ ߡߊߦߟߍ߬ߡߊ߲߫",
        "action-edituserjson": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߘߏ ߟߎ߬ ߟߊ߫ JSON ߞߐߕߐ߮ ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫",
        "action-edituserjs": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߘߏ ߟߎ߬ ߟߊ߫ JavaScript ߞߐߕߐ߮ ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫",
        "action-editmyusercss": "ߌ ߖߘߍ߬ߞߊ߬ߣߌ߲߬ CSS ߟߊ߬ߓߊ߰ߙߊ߬ߟߌ߬ ߞߐߕߐ߮ ߡߊߦߟߍ߬ߡߊ߲߫",
        "action-editmyuserjson": "ߌ ߖߘߍ߬ߞߊ߬ߣߌ߲߬ JSON ߞߐߕߐ߮ ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫",
        "action-editmyuserjs": "ߌ ߖߘߍ߬ߞߊ߬ߣߌ߲߬ JavaScript ߞߐߕߐ߮ ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫",
+       "action-editmyuserjsredirect": "ߌ ߖߘߍ߬ߞߊ߬ߣߌ߲߬ JavaScript ߞߐߕߐ߮ ߟߎ߬ ߡߊߦߟߍ߬ߡߊ߲߫ ߡߍ߲ ߠߎ߬ ߓߘߊ߫ ߟߊߞߎ߲߬ߛߌ߲߫.",
        "action-viewsuppressed": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߘߏ ߟߎ߬ ߟߊ߫ ߟߢߊ߬ߟߌ߬ ߢߡߊߘߏ߲߰ߣߍ߲ ߠߎ߬ ߦߋ߫",
+       "action-hideuser": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ߫ ߟߎ߫ ߓߊ߬ߟߌ߬߸ ߡߍ߲ ߠߎ߬ ߢߡߊߘߏ߲߰ߣߍ߲߬ ߦߋ߫ ߖߊ߬ߡߊ ߟߊ߫ ߦߋߟߌ ߡߊ߬.",
        "action-unblockself": "ߌ ߖߍ߬ߘߍ ߓߊ߬ߟߌ߬ߣߍ߲ ߓߐ߫",
+       "action-reupload-own": "ߌ ߖߘߍ߬ߞߊߣߌ߲ ߠߊ߫ ߞߐߕߐ߯ ߟߊߦߟߍ߬ߣߍ߲ ߠߎ߬ ߖߏ߰ߛߌ߬",
+       "action-nominornewtalk": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߘߋ߬ߣߍ߲߬ ߞߏ ߕߍ߫ ߘߊߘߐߖߊߥߏ ߞߐߜߍ ߟߎ߬ ߘߐ߫߸ ߗߋߛߓߍ߫ ߞߎߘߊ߫ ߘߊߡߌ߬ߣߊ߬ ߞߊߟߌߦߊ߫ ߘߐ߫.",
+       "action-markbotedits": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߟߊߞߐߛߊ߬ߦߌ߬ߣߍ߲ ߠߎ߬ ߣߐ߬ߣߐ߬ ߓߏߕ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ߣߐ ߘߌ߫.",
+       "action-patrolmarks": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߞߎߘߊ ߟߎ߬ ߦߌ߬ߘߊ߬ ߓߍ߬ߙߍ߲߬ߓߍ߬ߙߍ߲߬ߠߌ߲߫ ߣߐ߬ߣߐ߬ߣߍ߲ ߘߌ߫",
+       "action-override-export-depth": "ߞߐߜߍ ߟߎ߬ ߟߊߝߏ߬ߦߌ߬߸ ߤߊߟߌ߬ ߞߐߜߍ߫ ߜߋ߲߭ߞߘߎ߬ߣߍ߲ߢߐ߲߰ߠߊ ߡߍ߲ ߠߎ߬ ߦߋ߫ ߅ ߘߎ߲߰ߧߊ ߛߊ߲ߘߐ߫.",
+       "action-suppressredirect": "ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲ ߞߊߣߊ߬ ߟߊߘߊ߲߫ ߓߐߛߎ߲ ߞߐߜߍ ߟߎ߬ ߟߊ߫ ߞߐߜߍ ߟߎ߬ ߓߐ߫ ߕߎߡߊ ߟߴߊ߬ߟߎ߫ ߣߐ߭ ߘߐ߫.",
        "nchanges": "$1 {{PLURAL:$1|ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲|ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߠߎ߬}}",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|ߞߊ߬ߦߌ߯ ߓߐߒߡߊߟߌ ߟߊߓߊ߲}}",
        "enhancedrc-history": "ߘߐ߬ߝߐ",
        "recentchanges-timeout": "ߢߌߣߌ߲ߣߌ߲ ߣߌ߲߬ ߕߎ߬ߡߊ ߓߘߊ߫ ߕߊ߬ߡߌ߲߬. ߌ ߞߊߞߊ߲߫ ߞߊ߬ ߢߊߢߌߣߌ߲߫ ߜߘߍ߫ ߟߊ߬ߓߍ߲߬ߢߐ߲߰ߡߊ ߞߍ߫.",
        "recentchanges-network": "ߞߊ߬ ߓߍ߲߬ ߛߋߒߞߏߟߦߊ ߝߎ߬ߕߎ߲߬ߕߌ ߡߊ߬߸ ߞߐߝߟߌ߫ ߛߌ߫ ߕߍ߫ ߣߊ߬ ߛߋ߫ ߟߊ߫ ߟߊߢߎ߲߫ ߠߊ߫. ߌ ߞߊߘߊ߲߫ ߞߊ߬ ߞߐߜߍ ߣߌ߲߬ ߠߊߛߎߡߦߊ߫ ߖߊ߰ߣߌ߲߫.",
        "recentchanges-notargetpage": "ߞߐߜߍ ߕߐ߮ ߟߊߘߏ߲߬ ߛߊ߲ߝߍ߬߸ ߦߟߍ߬ߡߊ߲ ߡߍ߲ ߦߋ߫ ߞߐߜߍ ߘߐ߫߸ ߞߵߏ߬ ߦߋ߫.",
+       "recentchanges-feed-description": "ߥߞߌ ߣߌ߲߬ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߞߐ߯ߟߕߊ ߟߎ߬ ߣߐ߬ߣߐ߬ ߓߊߟߏ ߣߌ߲߬ ߘߐ߫.",
        "recentchanges-label-newpage": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߣߌ߲߬ ߓߘߊ߫ ߘߐߜߍ߫ ߞߎߘߊ ߟߊߘߊ߲߫",
        "recentchanges-label-minor": "ߢߟߊߞߎߘߦߊ߫ ߝߕߌߣߍ߲ ߠߋ߬",
        "recentchanges-label-bot": "ߡߐ߰ߡߐ߮ ߟߋ߫ ߣߐ߬ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ ߣߌ߲߬ ߞߍ߫ ߟߊ߫",
        "backend-fail-read": "ߞߐߕߐ߮ ߕߴߛߋ߫ ߘߐߞߊ߬ߙߊ߲߬ ߠߊ߫   \"$1\".",
        "backend-fail-create": "ߊ߬ ߕߍ߫ ߣߊ߬ ߛߐ߲߬ ߠߊ߫ ߞߐߕߐ߮  \"$1\" ߛߓߍ߫ ߟߊ߫.",
        "backend-fail-maxsize": "ߊ߫ ߕߍ߫ ߣߊ߬ ߞߐߕߐ߮  \"$1\" ߛߓߍ߫ ߟߊ߫߸ ߓߊߏ߬ ߊ߬ ߓߏ߲߬ߓߊ߫ ߞߊ߬ ߕߊ߬ߡߌ߲߬ {{PLURAL:$2|ߝߙߐ߬ߢߐ߬ ߞߋߟߋ߲߫|ߝߙߐ߬ߢߐ ߟߎ߬ $2}}.",
+       "backend-fail-stat": "ߊ߬ ߕߴߛߋ߫ ߞߐߕߐ߮ \"$1\" ߟߌ߬ߤߟߊ ߞߊ߬ߙߊ߲߬ ߠߊ߫.",
        "lockmanager-notlocked": "ߊ߬ ߕߍ߫ ߣߊ߬ ߛߐ߲߬ ߠߊ߫ \"$1\" ߟߊߞߊ߬ ߟߊ߫߸ ߊ߬ ߛߐ߰ߣߍ߲߬ ߕߍ߫.",
        "lockmanager-fail-closelock": "ߊ߬ ߕߍ߫ ߣߊ߬ ߛߋ߫ ߟߊ߫ \"$1\" ߞߐߕߐ߮ ߛߐ߰ߣߍ߲ ߘߊߕߎ߲߯ ߠߊ߫.",
        "lockmanager-fail-deletelock": "ߊ߬ ߕߍ߫ ߣߊ߬ ߛߋ߫ ߟߊ߫ \"$1\" ߞߐߕߐ߯ ߛߐ߰ߣߍ߲ ߖߏ߰ߛߌ߬ ߟߊ߫.",
        "license": "ߟߊ߬ߘߌ߬ߢߍ߬ߟߌ ߦߴߌ ߘߐ߫:",
        "license-header": "ߟߊ߬ߘߌ߬ߢߍ߬ߟߌ ߦߴߌ ߘߐ߫",
        "nolicense": "ߊ߬ ߡߊ߫ ߓߊߕߐ߬ߡߐ߲߬",
+       "licenses-edit": "ߕߌ߰ߦߊ ߢߣߊߕߊߟߌ ߡߊߦߟߍ߬ߡߊ߲߫",
        "upload_source_file": "(ߌ ߟߊ߫ ߞߐߕߐ߯ ߛߎߥߊ߲ߘߌߣߍ߲ ߠߎ߬ ߞߊ߬ ߝߘߊ߫ ߌ ߟߊ߫ ߕߟߋ߬ߓߊ߮ ߟߊ߫)",
        "listfiles-delete": "ߊ߬ ߖߏ߬ߛߌ߬",
        "listfiles-summary": "ߞߐߜߍ߫ ߓߟߏߡߊߞߊ߬ߣߍ߲ ߣߌ߲߬ ߦߴߌ ߟߊ߫ ߞߐߕߐ߯ ߟߊߦߟߍ߬ߣߍ߲ ߠߎ߬ ߓߍ߯ ߟߋ߬ ߦߌ߬ߘߊ߬ ߟߊ߫",
        "wantedpages": "ߞߐߜߍ߫ ߜߋ߬ߟߎ߲߬ߣߍ߲ ߠߎ߬",
        "wantedpages-badtitle": "ߞߎ߲߬ߕߐ߮ ߓߍ߲߬ߣߍ߲߬ ߕߍ߫ ߞߐߝߟߌ߫ ߦߌ߬ߘߊ߬ߣߍ߲: $1 ߘߐ߫",
        "wantedfiles": "ߞߐߜߍ߫ ߜߋ߬ߟߎ߲߬ߣߍ߲ ߠߎ߬",
+       "wantedfiletext-nocat-noforeign": "ߞߐߕߐ߮ ߢߌ߲߬ ߠߎ߬ ߓߘߊ߫ ߟߊߓߊ߯ߙߊ߫ ߞߏ߬ߣߵߊ߬ߟߎ߬ ߕߴߦߋ߲߬.",
        "wantedtemplates": "ߞߙߊߞߏ ߞߊ߬ߣߌ߲߬ߣߍ߲ ߠߎ߬",
        "mostlinked": "ߛߘߌ߬ߜߋ߲߬ ߦߙߌߞߊ߫ ߦߋ߫ ߞߐߜߍ ߡߍ߲ ߠߎ߬ ߘߐ߫",
        "mostlinkedcategories": "ߛߘߌ߬ߜߋ߲߬ ߦߙߌߞߊ߫ ߦߋ߫ ߦߌߟߡߊ ߡߍ߲ ߠߎ߬ ߘߐ߫",
        "protectedpages": "ߞߐߜߍ߫ ߟߊߞߊ߲ߘߊߣߍ߲ ߠߎ߬",
        "protectedpages-filters": "ߛߍ߲ߛߍ߲ߟߊ߲ ߠߎ߬:",
        "protectedpages-indef": "ߟߊ߬ߞߊ߲߬ߘߊ߬ߟߌ ߘߊ߲߬ߠߊߕߍ߰ߓߊߟߌ ߘߐߙߐ߲߫",
+       "protectedpages-summary": "ߞߐߜߍ ߛߙߍߘߍ ߢߌ߲߬ ߠߎ߬ ߦߋ߫ ߦߋ߫ ߞߐߜߍ߫ ߟߎ߫ ߟߋ߬ ߘߐ߫ ߡߍ߲ ߠߎ߬ ߟߊߞߊ߲ߘߊߣߍ߲߫ ߦߋ߫ ߕߊ߲߫. ߣߵߌ ߦߋ߫ ߞߎ߲߬ߕߐ߮ ߛߙߍߘߍ߫ ߟߎ߫ ߟߋ߬ ߞߐ߫ ߡߍ߲ ߠߎ߬ ߟߊߞߊ߲ߘߊߣߍ߲߫ ߦߋ߫ ߛߌ߲ߘߟߌ ߡߊ߬߸ ߣߌ߲߬ ߘߐߜߍ߫ [[{{#special:ProtectedTitles}}|{{int:protectedtitles}}]].",
        "protectedpages-noredirect": "ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲ ߢߡߊߘߏ߲߰",
        "protectedpages-timestamp": "ߕߎ߬ߡߊ ߓߊ߬ߘߌ߬ߟߊ߲",
        "protectedpages-page": "ߞߐߜߍ",
        "protect-cantedit": "ߌ ߕߍ߫ ߣߊ߬ ߛߋ߫ ߟߊ߫ ߞߐߜߍ ߣߌ߲߬ ߟߊ߬ߞߊ߲߬ߘߊ߬ߟߌ ߞߊߓߋ ߡߊߝߊ߬ߟߋ߲߬ ߠߊ߫߸ ߞߵߊ ߞߵߊ߬ ߡߊߛߐ߬ߘߐ߲߬ ߊ߬ ߡߊߦߟߍ߬ߡߊ߲ ߠߊߘߤߊ߬ߣߍ߲߬ ߕߴߌ ߦߋ߫.",
        "protect-othertime": "ߕߎ߬ߡߊ߬ ߜߘߍ:",
        "protect-othertime-op": "ߕߎ߬ߡߊ߬ ߜߘߍ߫",
+       "protect-existing-expiry": "ߕߋ߲߭ߕߋ߲߭ ߛߕߊߝߊ߫ ߕߎߡߊ: $3߸ $2",
        "protect-existing-expiry-infinity": "ߕߋ߲߭ߕߋ߲߭ ߛߕߊߝߊ߫ ߕߎߡߊ: ߘߊ߲߬ߓߊߟߌ",
        "protect-otherreason": "ߞߎ߲߬ ߡߊߞߊ߬ߝߏ߬ߕߊ߬/ߜߘߍ:",
        "protect-otherreason-op": "ߞߎ߲߬ ߜߘߍ ߟߎ߬",
        "protect-edit-reasonlist": "ߟߊ߬ߞߊ߲߬ߘߊ߬ߟߌ ߞߎ߲߭ ߡߊߦߟߍ߬ߡߊ߲߫",
        "protect-expiry-options": "ߕߎ߬ߡߊ߬ߙߋ߲߬ ߁: 1 hour, ߕߟߋ߬ ߁: 1 day, ߞߎ߲߬ߢߐ߲߰ ߁:1 week, ߞߎ߲߬ߢߐ߮ ߂:2 weeks, ߞߊߙߏ߫ ߁:1 month, ߞߊߙߏ߫ ߃:3 months, ߞߊߙߏ߫ ߆:6 months, ߛߊ߲߬ ߁:1 year, ߘߊ߲߬ߓߊߟߌ: infinite",
+       "restriction-type": "ߘߌ߬ߢߍ߬ߟߊ߬ߢߌ߬ߣߌ߲:",
        "minimum-size": "ߘߎ߰ߟߊ߬ߘߐ߬ ߢߊ߲ߞߊ߲",
        "maximum-size": "ߢߊ߲ߞߊ߲ ߞߐߘߊ߲:",
        "restriction-edit": "ߊ߬ ߡߊߦߟߍ߬ߡߊ߲߬",
        "version-ext-colheader-description": "ߕߐ߯ߟߊߘߏ߲",
        "version-ext-colheader-credits": "ߛߓߍߦߟߊ",
        "version-license-title": "$1 ߕߌ߰ߦߊ",
+       "version-poweredby-others": "ߘߏ߫ ߜߘߍ ߟߎ߬",
+       "version-poweredby-translators": "translatewiki.net ߘߟߊߡߌߘߊߟߊ߲",
+       "version-credits-summary": "ߊ߲ ߧߴߊ߬ ߝߍ߬ ߞߊ߬ ߡߐ߱ ߢߌ߲߬ ߠߎ߬ ߡߊߟߐ߲߫ ߞߊ߬ ߓߍ߲߬ ߊ߬ߟߎ߬ ߟߊ߫ ߓߟߏߓߌߟߊߢߐ߲߯ߞߊ߲ ߡߊ߬ [[Special:Version|MediaWiki]] ߘߐ߫.",
        "version-software": "ߛߎ߲ߝߘߍ ߓߘߊ߫ ߡߊߞߍ߫",
        "version-software-product": "ߥߟߏߒߘߐ",
        "version-software-version": "ߦߌߟߡߊ",
        "fileduplicatesearch-summary": "ߞߐߕߐ߯ ߓߊߟߌߣߍ߲ ߠߎ߬ ߢߌߣߌ߲߫ ߡߍ߲ ߠߎ߬ ߓߌ߲ߓߌ߲ߣߍ߲߫ ߦߋ߫ ߢߋߙߋ߲ߞߎߟߌ ߡߐ߬ߟߐ߲ ߡߊ߬.",
        "fileduplicatesearch-filename": "ߞߐߕߐ߮ ߕߐ߮:",
        "fileduplicatesearch-submit": "ߢߌߣߌ߲ߠߌ߲",
+       "fileduplicatesearch-result-1": "ߓߊߟߌߟߌ߫ ߡߊߟߐ߲ߣߍ߲߫ ߛߌ߫ ߕߍ߫ ߞߐߕߐ߮  \"$1\" ߡߊ߬.",
+       "fileduplicatesearch-noresults": "ߞߐߕߐ߯ ߛߌ߫ ߕߐ߯ ߡߊ߫ ߦߋ߫ ߞߏ߫  \"$1\".",
        "specialpages": "ߘߎ߲߬ߘߎ߬ߡߊ߬ ߞߐߜߍ ߟߎ߬",
+       "specialpages-group-other": "ߞߐߜߍ߫ ߓߟߏߡߊߞߊ߬ߣߍ߲ ߕߐ߭ ߟߎ߬",
+       "specialpages-group-login": "ߌ ߜߊ߲߬ߞߎ߲߬/ߖߊ߬ߕߋ߬ߘߊ ߘߏ߫ ߟߊߞߊ߬",
+       "specialpages-group-users": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߟߎ߬ ߣߌ߫ ߤߊߞߍ",
+       "specialpages-group-highuse": "ߞߐߜߍ߫ ߟߊߓߊ߯ߙߕߊ ߛߊ߲ߘߐߕߊ ߟߎ߬",
+       "specialpages-group-pages": "ߞߐߜߍ ߟߎ߬ ߛߙߍߘߍ",
+       "specialpages-group-pagetools": "ߞߐߜߍ ߖߐ߯ߙߊ߲ ߠߎ߬",
+       "specialpages-group-wiki": "ߕߎ߬ߡߊ߬ߘߊ ߣߌ߫ ߖߐ߯ߙߊ߲ ߠߎ߬",
+       "specialpages-group-redirects": "ߞߐߜߍ߫ ߞߙߍߞߙߍߣߍ߲ ߠߎ߬ ߟߊߞߎ߲߬ߛߌ߲ ߦߴߌ ߘߐ߫",
+       "specialpages-group-spam": "ߞߏ߲߬ߘߏ ߖߐ߯ߙߊ߲ ߠߎ߬",
+       "specialpages-group-developer": "ߟߊ߬ߥߙߌ߬ߞߌ߬ߟߌ ߖߐ߯ߙߊ߲ ߠߎ߬",
+       "blankpage": "ߞߐߜߍ߫ ߘߐߞߏߟߏ߲",
        "tag-filter": "[[Special:Tags|ߞߊ߲ߠߊߛߓߍ]] ߢߡߊߘߏ߲߰ߣߍ߲",
+       "tag-filter-submit": "ߥߊ߬ߣߊߙߌ",
        "tag-list-wrapper": "[[Special:Tags|{{PLURAL:$1|ߡߊ߬ߛߙߋ |ߡߊ߬ߛߙߋ ߟߎ߬ }}]]: $2",
+       "tag-mw-contentmodelchange": "ߞߣߐߘߐ ߛߎ߯ߦߊ ߡߊߝߊ߬ߟߋ߲߬ߠߌ߲",
+       "tag-mw-contentmodelchange-description": "ߣߌ߲߬ ߡߊߦߟߍ߬ߡߊ߲߫\n[https://www.mediawiki.org/wiki/Special:MyLanguage/Help:ߞߣߐߘߐߛߎ߯ߦߊߡߊߝߊ߬ߟߋ߲߬ ߞߣߐߘߐ ߛߎ߯ߦߊ ߡߊߝߊ߬ߟߋ߲߬] ߞߐߜߍ ߘߐ߫",
+       "tag-mw-new-redirect": "ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲߬ ߞߎߘߊ",
+       "tag-mw-new-redirect-description": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߍ߲ ߠߎ߬ ߞߊ߬ ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲ ߠߊߘߊ߲߫ ߥߟߊ߫ ߞߊ߬ ߞߐߜߍ ߦߟߍ߬ߡߊ߲߫ ߞߊ߬ ߞߍ߫ ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲ ߘߌ߫",
+       "tag-mw-removed-redirect": "ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲ ߛߋ߲߬ߓߐ߫",
+       "tag-mw-removed-redirect-description": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߍ߲ ߠߎ߬ ߞߊ߬ ߕߋ߲߭ߕߋ߲߭ ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲ ߡߊߦߟߍ߬ߡߊ߲߫ ߞߵߊ߬ ߞߍ߫ ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߓߊߟߌ ߘߌ߫",
+       "tag-mw-changed-redirect-target": "ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲ ߞߏ߲߭ ߓߘߊ߫ ߡߊߝߊ߬ߟߋ߲߬",
+       "tag-mw-changed-redirect-target-description": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߍ߲ ߠߎ߬ ߞߊ߬ ߟߊ߬ߞߎ߲߬ߛߌ߲߬ߠߌ߲ ߞߏ߲߭ ߡߊߝߊ߬ߟߋ߲߬",
+       "tag-mw-blank": "ߖߏ߰ߛߌ߬ߟߌ ߦߵߌ ߘߐ߫",
+       "tag-mw-blank-description": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߍ߲ ߠߎ߬ ߞߊ߬ ߞߐߜߍ ߖߏ߰ߛߌ߬",
+       "tag-mw-replace": "ߊ߬ ߓߘߊ߫ ߓߐ߫ ߊ߬ ߣߐ߭ ߘߐ߫",
+       "tag-mw-replace-description": "ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߍ߲ ߠߎ߬ ߞߊ߬ ߞߣߐߘߐ %߉߀ ߛߋ߲߬ߓߐ߫ ߞߐߜߍ ߘߐ߫",
+       "tag-mw-rollback": "ߟߊߞߐߛߊ߬ߦߌ߬",
+       "tag-mw-undo": "ߊ߬ ߘߐߛߊ߬",
+       "tag-mw-undo-description": "ߡߊߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߍ߲ ߠߎ߬ ߞߊ߬ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߟߐ߯ߟߊߣߍ߲ ߠߎ߬ ߘߐߛߊ߬ ߞߊ߬ ߘߐ߬ߛߊ߬ߟߌ ߛߘߌ߬ߜߋ߲ ߠߊߓߊ߯ߙߊ߫.",
+       "tags-title": "ߘߎ߲ߛߓߍ ߟߎ߬",
+       "tags-tag": "ߘߎ߲ߛߓߍ ߕߐ߮",
+       "tags-display-header": "ߟߊ߲ߞߣߍߡߊߟߌ ߡߊ߬ߦߟߍ߬ߡߊ߲߬ߠߌ߲߬ ߛߙߍߘߍ ߘߐ߫",
+       "tags-description-header": "ߞߘߐߝߐߟߌ ߞߊ߲߬ߛߓߍ߬ߟߌ߬ ߘߝߊߣߍ߲",
+       "tags-source-header": "ߛߎ߲",
+       "tags-active-header": "ߊ߬ ߟߊߞߎߣߎ߲߫ ߣߍ߲߫؟",
+       "tags-hitcount-header": "ߞߏ߲߭ ߓߘߊ߫ ߡߊߝߊ߬ߟߋ߲߬",
+       "tags-actions-header": "ߞߍߟߌ ߟߎ߬",
        "tags-active-yes": "ߐ߲߬ߐ߲߬ߐ߲߫",
        "tags-active-no": "ߍ߲߬ߍ߲ߍ߲߬",
+       "tags-source-extension": "ߡߊ߬ߕߍ߰ߣߍ߲ ߠߎ߬ ߛߎ߲ߝߘߍ ߓߟߏ߫",
+       "tags-source-manual": "ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߣߌ߫ ߓߏߕ ߟߎ߬ ߟߊ߫ ߓߟߏߟߊ߫ ߞߍߟߌ",
+       "tags-source-none": "ߊ߬ ߕߍߣߊ߬ ߥߊ߯ߕߌߖߊ߲߫ ߞߍ߫ ߟߊ߫ ߓߊ߯ߙߊ ߘߐ߫ ߡߎ߬ߕߎ߲߬",
+       "tags-edit": "ߊ߬ ߡߊߦߟߍ߬ߡߊ߲߬",
+       "tags-delete": "ߊ߬ ߖߏ߰ߛߌ߬",
+       "tags-activate": "ߊ߬ ߟߊߞߎߣߎ߲߫",
+       "tags-deactivate": "ߊ߬ ߟߊߛߎ߬ߣߐ߬",
        "tags-hitcount": "{{PLURAL:$1|ߦߟߍ߬ߡߊ߲߬ߠߌ|$1 ߦߟߍ߬ߡߊ߲߬ߠߌ ߠߎ߬}}",
+       "tags-manage-no-permission": "ߌ ߟߊߘߌ߬ߢߍ߬ߣߍ߲߬ ߕߍ߫ ߞߊ߬ ߘߎ߲ߛߓߍ ߡߊߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߊߞߍ߲߰.",
+       "tags-manage-blocked": "ߌ ߕߍ߫ ߣߊ߬ ߛߋ߫ ߟߊ߫ ߘߎ߲ߛߓߍ ߡߊߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߡߊߞߍ߲߰ ߠߊ߫ ߞߊ߬ {{GENDER:$1|ߌ}} ߓߊ߬ߟߌ߬ߣߍ߲ ߕߏ߫.",
+       "tags-create-heading": "ߘߎ߲ߛߓߍ߫ ߞߎߘߊ߫ ߛߌ߲ߘߌ",
+       "tags-create-explanation": "ߘߊ߲ߛߎ߲ ߞߏߛߐ߲߬߸ ߘߎ߲ߛߓߍ ߟߊߘߊ߲ߣߍ߲߫ ߞߎߘߊ ߟߎ߬ ߘߌ߫ ߣߊ߬ ߛߌ߲ߘߌ߫߸ ߊ߬ ߣߌ߫ ߞߊ߬ ߞߍ߫ ߦߋ߲߬ ߟߊ߬ߓߊ߰ߙߊ߬ߟߊ ߣߌ߫ ߓߏߕ ߟߊ߫ ߟߊ߬ߓߊ߰ߙߊ߬ߟߌ ߞߊ߲ߡߊ߬.",
+       "tags-create-tag-name": "ߘߎ߲ߛߓߍ ߕߐ߮:",
+       "tags-create-reason": "ߊ߬ ߛߊߓߎ:",
+       "tags-create-submit": "ߟߊ߬ߘߊ߲߬ߠߌ߲",
+       "tags-create-no-name": "ߌ ߞߊߞߊ߲߫ ߞߊ߬ ߘߎ߲ߛߓߍ ߕߐ߮ ߘߏ߫ ߞߙߍߞߙߍ߫.",
        "logentry-delete-delete": "$1 {{GENDER:$2|deleted}} ߞߐߜߍ $3",
        "logentry-delete-restore": "$1 $3($4) ߞߐߜߍ {{GENDER:$2|ߓߘߊ߫ ߟߊߛߊ߬ߦߌ߬ ߞߐ߫}}",
        "logentry-delete-revision": "$1  {{GENDER:$2|ߓߘߊ߫ ߦߟߍ߬ߡߊ߲߬ߠߌ߲ ߞߍ߫}} ߣߌ߲߬ ߦߋߗߏ߮ ߟߊ߫ {{PLURAL:$5|a revision|$5 revisions}} ߞߐߜߍ ߣߌ߲߬ $3: $4 ߘߐ߫",
index 384e7ae..2ec2e44 100644 (file)
                        "Railfail536",
                        "Vlad5250",
                        "CiaPan",
-                       "BadDog"
+                       "BadDog",
+                       "Rail",
+                       "Maro21"
                ]
        },
        "tog-underline": "Podkreślenie linków:",
        "tog-useeditwarning": "Ostrzegaj mnie, gdy opuszczam stronę edycji bez zapisania zmian",
        "tog-prefershttps": "Zawsze używaj bezpiecznego połączenia po zalogowaniu",
        "tog-showrollbackconfirmation": "Wyświetl komunikat potwierdzający kliknięcie linku wycofującego edycje",
+       "tog-requireemail": "Wymagaj adresu e-mail przy resetowaniu hasła",
        "underline-always": "Zawsze",
        "underline-never": "Nigdy",
        "underline-default": "według ustawień skórki lub przeglądarki",
        "undo-norev": "Edycja nie może być cofnięta, ponieważ nie istnieje lub została usunięta.",
        "undo-nochange": "Wygląda na to, że edycja została już anulowana.",
        "undo-summary": "Anulowanie wersji $1 autorstwa [[Special:Contributions/$2|$2]] ([[User talk:$2|dyskusja]])",
+       "undo-summary-anon": "Anulowanie wersji $1 autorstwa [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Anulowanie wersji $1 autorstwa ukrytego użytkownika",
        "cantcreateaccount-text": "Tworzenie konta z tego adresu IP ('''$1''') zostało zablokowane przez [[User:$3|$3]].\n\nPodany przez $3 powód to ''$2''",
        "cantcreateaccount-range-text": "Tworzenie konta z adresów IP w zakresie <strong>$1</strong>, zawierającego twój adres IP (<strong>$4</strong>), zostało zablokowane przez [[User:$3|$3]].\n\nPodany przez $3 powód to <em>$2</em>",
        "searchall": "wszystkie",
        "showingresults": "Poniżej znajduje się lista {{PLURAL:$1|z '''1''' wynikiem|'''$1''' wyników}}, rozpoczynając od wyniku numer '''$2'''.",
        "showingresultsinrange": "Poniżej wyświetlono co najwyżej {{PLURAL:$1|<strong>1</strong> wynik|<strong>$1</strong> wyniki|<strong>$1</strong> wyników}} w zakresie od <strong>$2</strong> do <strong>$3</strong>.",
-       "search-showingresults": "{{PLURAL:$4|Wynik <strong>$1</strong> z <strong>$3</strong>|Wyniki <strong>$1 - $2</strong> z <strong>$3</strong>}}",
+       "search-showingresults": "{{PLURAL:$4|Wynik <strong>$1</strong> z <strong>$3</strong>|Wyniki <strong>$1  $2</strong> z <strong>$3</strong>}}",
        "search-nonefound": "Brak wyników spełniających kryteria podane w zapytaniu.",
        "search-nonefound-thiswiki": "Brak wyników spełniających kryteria podane w zapytaniu.",
        "powersearch-legend": "Wyszukiwanie zaawansowane",
        "prefs-help-email": "Podanie adresu e‐mail nie jest obowiązkowe, lecz jest konieczne do zresetowania zapomnianego hasła.",
        "prefs-help-email-others": "Możesz również umożliwić innym użytkownikom wysłanie do Ciebie e‐maila poprzez Twoją stronę użytkownika lub stronę dyskusji (bez ujawniania Twojego adresu).",
        "prefs-help-email-required": "Wymagany jest adres e‐mail.",
+       "prefs-help-requireemail": "Po zaznaczeniu wiadomości e-mail z linkiem do resetu hasła będą wysyłane dopiero gdy resetujący użytkownik wprowadzi zarówno nazwę użytkownika jak i adres e-mail przypisane do tego konta.",
        "prefs-info": "Podstawowe informacje",
        "prefs-i18n": "Ustawienia językowe",
        "prefs-signature": "Podpis",
        "alreadyrolled": "Nie można dla strony [[:$1|$1]] cofnąć ostatniej zmiany, którą wykonał [[User:$2|$2]] ([[User talk:$2|dyskusja]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]).\nKtoś inny zdążył już to zrobić lub wprowadził własne poprawki do treści strony.\n\nAutorem ostatniej zmiany jest teraz [[User:$3|$3]] ([[User talk:$3|dyskusja]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Edycję opisał: <em>$1</em>.",
        "revertpage": "Wycofano edycje użytkownika [[Special:Contributions/$2|$2]] ([[User talk:$2|dyskusja]]). Autor przywróconej wersji to [[User:$1|$1]].",
+       "revertpage-anon": "Wycofano edycje użytkownika [[Special:Contributions/$2|$2]]. Autor przywróconej wersji to [[User:$1|$1]].",
        "revertpage-nouser": "Wycofano edycje ukrytego użytkownika. Autor przywróconej wersji to {{GENDER:$1|[[User:$1|$1]]}}.",
        "rollback-success": "Wycofano edycje {{GENDER:$3|użytkownika|użytkowniczki}} $1;\nprzywrócono ostatnią wersję autorstwa {{GENDER:$4|$2}}.",
        "sessionfailure-title": "Błąd sesji",
        "ipblocklist-legend": "Znajdź zablokowanego użytkownika",
        "blocklist-userblocks": "Ukryj blokady konta",
        "blocklist-tempblocks": "Ukryj tymczasowe blokady",
+       "blocklist-indefblocks": "Ukryj blokady nałołożone na zawsze",
        "blocklist-addressblocks": "Ukryj blokady pojedynczych adresów IP",
        "blocklist-type": "Typ:",
        "blocklist-type-opt-all": "Wszystkie",
        "tooltip-p-logo": "Strona główna",
        "tooltip-n-mainpage": "Zobacz stronę główną",
        "tooltip-n-mainpage-description": "Przejdź na stronę główną",
-       "tooltip-n-portal": "O projekcie - co możesz zrobić, gdzie możesz znaleźć informacje",
+       "tooltip-n-portal": "O projekcie  co możesz zrobić, gdzie możesz znaleźć informacje",
        "tooltip-n-currentevents": "Informacje o aktualnych wydarzeniach",
        "tooltip-n-recentchanges": "Lista ostatnich zmian w {{GRAMMAR:MS.lp|{{SITENAME}}}}.",
        "tooltip-n-randompage": "Załaduj losową stronę",
index 150fa14..622ab51 100644 (file)
        "tog-useeditwarning": "Avisar-me quando eu deixar uma janela de edição sem ter salvo as alterações",
        "tog-prefershttps": "Usar sempre uma conexão segura enquanto estiver conectado",
        "tog-showrollbackconfirmation": "Mostrar um aviso de confirmação ao clicar em um link de reversão",
+       "tog-requireemail": "Exigir e-mail para redefinições de senha",
        "underline-always": "Sempre",
        "underline-never": "Nunca",
        "underline-default": "Padrão do navegador/tema",
        "undo-norev": "A edição não pôde ser desfeita porque não existe ou foi apagada.",
        "undo-nochange": "Parece que a edição já foi desfeita.",
        "undo-summary": "Desfeita a edição $1 de [[Special:Contributions/$2|$2]] ([[User talk:$2|Discussão]])",
+       "undo-summary-anon": "Desfazer revisão $1 por [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Desfazer a revisão $1 de um usuário oculto",
        "cantcreateaccount-text": "Este IP ('''$1''') foi bloqueado de criar novas contas por [[User:$3|$3]].\n\nA justificativa apresentada por $3 foi ''$2''",
        "cantcreateaccount-range-text": "A criação de conta a partir dos endereços IP no intervalo <strong>$1</strong>, que inclui o seu endereço IP (<strong>$4</strong>), foi bloqueada por [[User:$3|$3]].\n\nA razão dada por $3 é <em>$2</em>",
        "prefs-help-email": "O endereço de e-mail é opcional, mas será necessário para recriar sua senha caso esqueça a antiga.",
        "prefs-help-email-others": "Você também pode optar por permitir que outros entrem em contato com você através de sua página de usuário ou de discussão sem ter de revelar seus dados pessoais.",
        "prefs-help-email-required": "O endereço de e-mail é requerido.",
+       "prefs-help-requireemail": "Se marcado, só enviará emails de redefinição de senha se a pessoa que redefiniu tiver fornecido o nome de usuário e o e-mail para esta conta.",
        "prefs-info": "Informações básicas",
        "prefs-i18n": "Internacionalização",
        "prefs-signature": "Assinatura",
        "alreadyrolled": "Não foi possível reverter a última edição de [[:$1]] por [[User:$2|$2]] ([[User talk:$2|discussão]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]);\nalguém já editou ou reverteu a página.\n\nA última edição da página foi feita por [[User:$3|$3]] ([[User talk:$3|discussão]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "O sumário de edição era: <em>$1</em>.",
        "revertpage": "Foram revertidas as edições de [[Special:Contributions/$2|$2]] ([[User talk:$2|disc]]) para a última versão por [[User:$1|$1]]",
+       "revertpage-anon": "Foram revertidas as edições de [[Special:Contributions/$2|$2]] para a última versão por [[User:$1|$1]]",
        "revertpage-nouser": "Revertidas as edições de um usuário oculto para a última revisão de {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Edições revertidas por {{GENDER:$3|$1}};\nalterado para a última revisão por {{GENDER:$4|$2}}.",
        "sessionfailure-title": "Erro de sessão",
        "ipblocklist-legend": "Procurar por um usuário bloqueado",
        "blocklist-userblocks": "Esconder bloqueios de contas",
        "blocklist-tempblocks": "Esconder bloqueios temporários",
+       "blocklist-indefblocks": "Ocultar bloqueios indefinidos",
        "blocklist-addressblocks": "Esconder bloqueios de IP único",
        "blocklist-type": "Tipo:",
        "blocklist-type-opt-all": "Todos",
index 420912d..a33608f 100644 (file)
        "tog-useeditwarning": "Used as label for the checkbox in [[Special:Preferences#mw-prefsection-editing|Special:Preferences]].",
        "tog-prefershttps": "Toggle option used in [[Special:Preferences]] that indicates if the user wants to use a secure connection when logged in",
        "tog-showrollbackconfirmation": "Toggle option used in [[Special:Preferences]] to enable/disable rollback confirmation prompt. Should be visible only to users with rollback rights.",
+       "tog-requireemail": "Toggle option used in [[Special:Preferences]].  Should be only visible to users who have confirmed their email address.\n\nSee also: {{msg-mw|prefs-help-requireemail}}",
        "underline-always": "Used in [[Special:Preferences#mw-prefsection-rendering|Preferences]].\n\nThis option means \"always underline links\", there are also options {{msg-mw|Underline-never}} and {{msg-mw|Underline-default}}.\n\n{{Gender}}\n{{Identical|Always}}",
        "underline-never": "Used in [[Special:Preferences#mw-prefsection-rendering|Preferences]].\n\nThis option means \"never underline links\", there are also options {{msg-mw|Underline-always}} and {{msg-mw|Underline-default}}.\n\n{{Gender}}\n{{Identical|Never}}",
        "underline-default": "Used in [[Special:Preferences#mw-prefsection-rendering|Preferences]].\n\nThis option means \"underline links as in your user skin or your browser\", there are also options {{msg-mw|Underline-never}} and {{msg-mw|Underline-always}}.\n\n{{Gender}}\n{{Identical|Browser default}}",
        "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}}",
        "blockedtext-composite": "Text displayed to requests blocked by more than one block.\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 - details of the individual blocks that this block is made from\n* $6 - the expiry of the block with the longest duration\n* $7 - (Unused) the intended target of the block\n* $8 - the timestamp when the block started\nSee also:\n* {{msg-mw|Systemblockedtext|notext=1}}",
        "blockedtext-composite-ids": "Text displayed when a user is blocked by multiple blocks, if at least one block comes from the database.\n\nParameters:\n* $1 - IDs of the blocks from the database",
-       "blockedtext-composite-no-ids": "IP가 블랙리스트에 올라간 경우 여러 차단으로 사용자를 차단할 때 표시되는 텍스트 입니다.",
+       "blockedtext-composite-no-ids": "Text displayed when a user is blocked by multiple blocks, if all the blocks are due to the IP being blacklisted.",
        "blockedtext-composite-reason": "Reason given to blocked users who are affected by more than one block.\n\nSee also:\n* {{msg-mw|blockedtext-composite}}",
        "whitelistedittext": "Used as error message. Parameters:\n* $1 - a link to [[Special:UserLogin]] with {{msg-mw|loginreqlink}} as link description\n* $2 - an URL to the same\n\nSee also:\n* {{msg-mw|Nocreatetext}}\n* {{msg-mw|Uploadnologintext}}\n* {{msg-mw|Loginreqpagetext}}",
        "confirmedittext": "Used as error message.",
        "prefs-help-email": "Shown as explanation text on [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}.\n\nSee also:\n* {{msg-mw|prefs-help-email-required|help}}\n* {{msg-mw|prefs-help-email-others|help}}\n* {{msg-mw|prefs-changeemail|link title}}\n* {{msg-mw|prefs-setemail|link title}}",
        "prefs-help-email-others": "This text is shown on account creation, below the description of the e-mail address field (which is optional).\n\nSee also:\n* {{msg-mw|prefs-help-email-required|help}}\n* {{msg-mw|prefs-help-email|help}}\n* {{msg-mw|prefs-changeemail|link title}}\n* {{msg-mw|prefs-setemail|link title}}",
        "prefs-help-email-required": "Shown as explanation text on [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}.\n\nSee also:\n* {{msg-mw|prefs-help-email|help}}\n* {{msg-mw|prefs-help-email-others|help}}\n* {{msg-mw|prefs-changeemail|link title}}\n* {{msg-mw|prefs-setemail|link title}}",
+       "prefs-help-requireemail": "Shown as explanation text on [[Special:Preferences]] > {{int:prefs-personal}} > {{int:email}}.\n\nSee also: {{msg-mw|tog-requireemail}}",
        "prefs-info": "Header for the box giving basic information on the user account, displayed on the 'user profile' tab of the [[Special:Preferences|user preferences]] special page.\n{{Identical|Basic information}}",
        "prefs-i18n": "Field set legend for user preferences regarding the interface language",
        "prefs-signature": "{{Identical|Signature}}",
        "ipblocklist-legend": "Used as legend of the form in [[Special:BlockList]].\n\nSee also:\n* {{msg-mw|Ipblocklist-legend}}\n* {{msg-mw|Ipblocklist-submit}}",
        "blocklist-userblocks": "Used as the label for the multi-select checkbox in the form on [[Special:BlockList]].\n{{Related|Blocklist-blocks}}",
        "blocklist-tempblocks": "Used as the label for the multi-select checkbox in the form on [[Special:BlockList]].\n{{Related|Blocklist-blocks}}",
+       "blocklist-indefblocks": "Used as the label for the multi-select checkbox in the form on [[Special:BlockList]].\n{{Related|Blocklist-blocks}}",
        "blocklist-addressblocks": "Used as the label for the multi-select checkbox in the form on [[Special:BlockList]].\n{{Related|Blocklist-blocks}}",
        "blocklist-type": "Used as label for dropdown box in [[Special:BlockList]].",
        "blocklist-type-opt-all": "Used as option for dropdown box in [[Special:BlockList]]. This is the default option and indicates that \"all\" blocks will be listed\n{{Identical|All}}",
index a55c17d..ceb5005 100644 (file)
        "printableversion": "Versione ca se stambe",
        "permalink": "Collegamende ca remane pe sembre",
        "print": "Stambe",
-       "view": "Vide",
+       "view": "'Ndruche",
        "view-foreign": "'Ndruche sus a $1",
        "edit": "Cange",
        "edit-local": "Cange 'a descrizione locale",
        "create-local": "Aggiunge 'a descrizione locale",
        "delete": "Scangìlle",
        "undelete_short": "Annulle {{PLURAL:$1|'nu camgiamende|$1 cangiaminde}}",
-       "viewdeleted_short": "Vide {{PLURAL:$1|'nu cangiamende scangellate|$1 cangiaminde scangellate}}",
+       "viewdeleted_short": "'Ndruche {{PLURAL:$1|'nu cangiamende scangellate|$1 cangiaminde scangellate}}",
        "protect": "Prutette",
        "protect_change": "cange",
        "unprotect": "Cange 'a protezione",
        "tool-link-userrights": "Cange le gruppe {{GENDER:$1|utinde}}",
        "tool-link-userrights-readonly": "'Ndruche le gruppe {{GENDER:$1|utinde}}",
        "tool-link-emailuser": "Manne 'na mail a stu {{GENDER:$1|utende}}",
-       "imagepage": "Vide a pàgene de le file",
-       "mediawikipage": "Vide a pàgene de le messàgge",
-       "templatepage": "Vide a pàgene de le template",
-       "viewhelppage": "Vide a pàgene de l'ajute",
-       "categorypage": "Vide a pàgene de le categorije",
-       "viewtalkpage": "Vide le 'ngazzaminde",
+       "imagepage": "'Ndruche 'a pàgene de le file",
+       "mediawikipage": "'Ndruche 'a pàgene de le messàgge",
+       "templatepage": "'Ndruche 'a pàgene de le template",
+       "viewhelppage": "'Ndruche 'a pàgene de l'ajute",
+       "categorypage": "'Ndruche 'a pàgene de le categorije",
+       "viewtalkpage": "'Ndruche le 'ngazzaminde",
        "otherlanguages": "Jndr'à l'otre lènghe",
        "redirectedfrom": "(Riderette da $1)",
        "redirectpagesub": "Pàgene de redirezione",
        "ipblocklist-legend": "Iacchije 'n'utende blocchete",
        "blocklist-userblocks": "Scunne le blocche sus a le cunde de l'utinde",
        "blocklist-tempblocks": "Scunne le blocche temboranèe",
+       "blocklist-indefblocks": "Scunne le blocche indefinite",
        "blocklist-addressblocks": "Scunne le blocche de le IP singole",
        "blocklist-type": "Tipe:",
        "blocklist-type-opt-all": "Tutte",
index d6094cd..b103404 100644 (file)
        "tog-useeditwarning": "Предупреждать, когда я покидаю страницу с несохранёнными изменениями",
        "tog-prefershttps": "Всегда использовать защищённое соединение после представления системе",
        "tog-showrollbackconfirmation": "Запрашивать подтверждение при нажатии ссылки для отката",
+       "tog-requireemail": "Требовать адрес электронной почты для сброса пароля",
        "underline-always": "Всегда",
        "underline-never": "Никогда",
        "underline-default": "Использовать настройки браузера",
        "undo-norev": "Правка не может быть отменена, так как её не существует или она была удалена.",
        "undo-nochange": "Правка, похоже, уже была отменена.",
        "undo-summary": "Отмена правки $1, сделанной [[Special:Contributions/$2|$2]] ([[User talk:$2|обсуждение]])",
+       "undo-summary-anon": "Отмена версии $1 от [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Отмена правки $1, сделанной участником, чьё имя скрыто",
        "cantcreateaccount-text": "Создание учётных записей с этого IP-адреса (<strong>$1</strong>) было заблокировано {{GENDER:$3|участником|участницей|}} [[User:$3|$3]].\n\n$3 {{GENDER:$3|указал|указала}} следующую причину: <em>$2</em>.",
        "cantcreateaccount-range-text": "{{GENDER:$3|Участник|Участница}} [[User:$3|$3]] {{GENDER:$3|установил|установила}} запрет на создание учётных записей для диапазона IP-адресов <strong>$1</strong>, включающего ваш IP-адрес (<strong>$4</strong>). \n\nБыла указана следующая причина: <em>$2</em>.",
        "prefs-help-email": "Адрес почты не обязателен, но это единственный способ восстановить забытый пароль.",
        "prefs-help-email-others": "Он также позволит другим участникам связаться с вами по электронной почте с помощью ссылки на вашей персональной странице или на вашей странице обсуждения. При этом ваш адрес электронной почты не будет никому раскрыт.",
        "prefs-help-email-required": "Необходимо указать адрес электронной почты.",
+       "prefs-help-requireemail": "Если этот флажок установлен, электронные письма для сброса пароля будут отправляться только в том случае, если лицо, осуществляющее сброс, указало для этой учётной записи и имя пользователя, и адрес электронной почты.",
        "prefs-info": "Основные сведения",
        "prefs-i18n": "Интернационализация",
        "prefs-signature": "Подпись",
        "alreadyrolled": "Невозможно откатить последние изменения страницы «[[:$1]]», совершённые [[User:$2|$2]] ([[User talk:$2|обсуждение]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]),\nпоскольку кто-то другой уже успел откатить эти правки или отредактировать страницу.\n\nПоследние изменения {{GENDER:$3|внёс|внесла}} [[User:$3|$3]] ([[User talk:$3|обсуждение]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Было дано описание изменения: <em>$1</em>.",
        "revertpage": "Откат правок [[Special:Contributions/$2|$2]] ([[User talk:$2|обсуждение]]) к версии [[User:$1|$1]]",
+       "revertpage-anon": "Откат правок [[Special:Contributions/$2|$2]] к последней версии от [[User:$1|$1]]",
        "revertpage-nouser": "Откат правок (имя участника скрыто) к версии {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Откачены правки {{GENDER:$3|$1}}; возвращена последняя версия {{GENDER:$4|$2}}.",
        "sessionfailure-title": "Ошибка сеанса",
        "ipblocklist-legend": "Поиск заблокированного участника",
        "blocklist-userblocks": "Скрыть блокировки учётных записей",
        "blocklist-tempblocks": "Скрыть временные блокировки",
+       "blocklist-indefblocks": "Скрыть неопределённые блокировки",
        "blocklist-addressblocks": "Скрыть блокировки отдельных IP",
        "blocklist-type": "Тип:",
        "blocklist-type-opt-all": "Все",
index d5a801c..332a02e 100644 (file)
                ]
        },
        "tog-underline": "ڳنڍڻي هيٺان لڪير:",
-       "tog-hideminor": "تازين تبديلين منجھہ معمولي تبديليون لڪايو",
+       "tog-hideminor": "تازين تبديلين ۾ معمولي سنوارون لڪايو",
        "tog-hidepatrolled": "تازيون نگرانيل تبديليون لڪايو",
-       "tog-newpageshidepatrolled": "نَوَن صفحن واري فهرست مان نگرانيل صفحا لڪايو",
+       "tog-newpageshidepatrolled": "نَوَن صفحن جي فھرست مان گشت-ڪيل صفحا لڪايو",
        "tog-hidecategorization": "صفحن جا زمرا لڪايو",
-       "tog-extendwatchlist": "تازÙ\87 ØªØ±Ù\8aÙ\86 Ø¨Ø¯Ø±Ø§Ù\86 Ø³Ù\85Ù\88رÙ\8aÙ\88Ù\86 ØªØ¨Ø¯Ù\8aÙ\84Ù\8aÙ\88Ù\86 Ú\8fÙ\8aکارڻ Ù\84اءÙ\90 Ø²Ù\8aر Ù\86ظر Ù\81Ù\87رست Ú©Ù\8a Ù\88سÙ\8aع ÚªØ±Ù\8aÙ\88.",
+       "tog-extendwatchlist": "رڳÙ\88 ØªØ§Ø²Û\81 ØªØ±Ù\8aÙ\86 Ù\86Û\81Ø\8c Ø³Ù\85Ù\88رÙ\8aÙ\88Ù\86 ØªØ¨Ø¯Ù\8aÙ\84Ù\8aÙ\88Ù\86 Ú\8fÙ\8aکارڻ Ù\84اءÙ\90 Ù\86ظر Û¾ Ù\81ھرست Ú©Ù\8a Ú¦Ú¾Ù\84اÙ\8aÙ\88",
        "tog-numberheadings": "سُرخين کي خودڪاراً نمبر ڏيو",
        "tog-editondblclick": "ٻٽي ڪلڪ تي صفحا سنواريو",
        "tog-editsectiononrightclick": "ڀاڱن جي عنوان کي رائيٽ ڪلڪ ڪري سنوارڻ واري سھولت کي ڪارگر بڻايو",
        "tog-watchmoves": "جيڪي صفحا ۽ فائيل آءُٗ چوريان، سي منهنجي نظر ۾ فھرست ۾ شامل ڪريو",
        "tog-watchdeletion": "آءُٗ جيڪي صفحا ۽ فائيل  ڊاهيان، سي منهنجي نظر ۾ فھرست تي رکو",
        "tog-watchuploads": "منھنجا نوان چاڙهيل فائيلس نظر ۾ فھرست ۾ شامل ڪريو",
-       "tog-watchrollback": "انهن صفحن کي منهنجي نظر ۾ فھرست تي رکو، جن ۾ تبديلين کي مون واپس ورايو آهي",
+       "tog-watchrollback": "انھن صفحن کي منھنجي نظر ۾ فھرست تي رکو، جتي مون واپس ورائڻ جو عمل آهي.",
        "tog-minordefault": "سمورين سنوارن کي پاڻمرادو معمولي طور نشان لڳايو",
        "tog-previewontop": "سنوار دٻيءَ مٿان پيش-نگاھ ڏيکاريو",
        "tog-previewonfirst": "پھرين سنوار تي پيش-نگاھ ڏيکاريو",
-       "tog-enotifwatchlistpages": "منهنجي نظر ۾ فھرست اندر شامل ڪنهن صفحي يا فائيل ۾ تبديل پيش اچي مون کي برقٽپال اماڻيو",
+       "tog-enotifwatchlistpages": "منھنجي نظر ۾ فھرست ۾ شامل ڪو صفحو يا فائيل بدلايو وڃي تہ مون کي برقٽپال اماڻيو",
        "tog-enotifusertalkpages": "منهنجي مباحثي صفحي ۾ تبديليءَ جي صورت ۾ مون کي برقٽپال اماڻيو",
        "tog-enotifminoredits": "صفحن ۽ فائيلن جي معمولي سنوارن بابت بہ مون کي برقٽپال ڪريو",
        "tog-enotifrevealaddr": "پڌراين ۾ منهنجو برقٽپال پتو ظاهر ڪريو",
        "youhavenewmessagesfromusers": "{{PLURAL:$4|توھان کي}} {{PLURAL:$3|ٻي واپرائيندڙ|$3 واپرائيندڙن}} ($2) کان $1 آھن.",
        "youhavenewmessagesmanyusers": "توهان لاءِ ڪيترن ئي واپرائيندڙن ($2) طرفان $1 آهن.",
        "newmessageslinkplural": "{{PLURAL:$1|ھڪ نئون پيغام|999=نوان پيغام}}",
-       "newmessagesdifflinkplural": "آخرÙ\8a {{PLURAL:$1|تبدÙ\8aÙ\84Ù\8a|999=تبدÙ\8aÙ\84Ù\8aÙ\88Ù\86}}",
+       "newmessagesdifflinkplural": "آخرÙ\8a {{PLURAL:$1|بدÙ\84اءÙ\8f|999=بدÙ\84اءÙ\8e}}",
        "youhavenewmessagesmulti": "$1 تي توهان لاءِ نوان نياپا آهن",
        "editsection": "سنواريو",
        "editold": "سنواريو",
        "databaseerror-query": "استفسار: $1",
        "databaseerror-function": "ڪاڄ: $1",
        "databaseerror-error": "چُڪَ: $1",
-       "laggedslavemode": "<strong>Ú\86تاءÙ\8f:</strong> ØµÙ\81Ø­Ù\8a Û¾ Ú¾Ø§Ú»Ù\88ÚªÙ\8aÙ\88Ù\86 ØªØ¨Ø¯Ù\8aÙ\84Ù\8aÙ\88Ù\86 Ù\86Ù\87 Ú¾Ø¬Ú» Ø¬Ù\88 Ø§Ù\85ڪاÙ\86 Ø¢Ú¾ي.",
+       "laggedslavemode": "<strong>Ú\86تاءÙ\8f:</strong> ØµÙ\81Ø­Ù\88 Ø´Ø§Ù\8aد Ú¾Ø§Ú»Ù\88ÚªÙ\8aÙ\88Ù\86 Ø¬Ø¯ØªÙ\88Ù\86 Ù\86Û\81 Ø±Ú©Ù\86دÙ\88 Ú¾Ø¬ي.",
        "readonly": "اعدادخانو بنديل",
        "missingarticle-rev": "(ڀيرو#: $1)",
        "missingarticle-diff": "(تفاوت: $1، $2)",
        "protectedpagetext": "هيءُ صفحو سوارڻ ۽ ٻين عملن کان بچائڻ لاءِ تحفظيو ويو آهي.",
        "viewsourcetext": "توهان هن صفحي جو ڪوڊ ڏسي ۽ نقل ڪري سگھو ٿا.",
        "viewyourtext": "توھان ھاڻي ھن صفحي ۾ <strong>پنھنجي سنوارن</strong> جو ذريعو ڏسي ۽ نقل ڪري سگھو ٿا.",
-       "protectedinterface": "هي صفحو سافٽ ويئر جو انٽرفيس متعين ڪري ٿو ۽ غلط استعال کان بچڻ لاءِ ان کي تحفظيو ويو آهي.\nتمام وڪي ۾ ترجمو شامل ڪرڻ لاءِ يا هن ۾ تبديلي ڪرڻ لاءِ ميڊياوڪي ترجمو [https://translatewiki.net/ translatewiki.net] استعمال ڪيو.",
+       "protectedinterface": "هي صفحو سافٽ ويئر جو انٽرفيس متعين ڪري ٿو ۽ غلط استعال کان بچڻ لاءِ ان کي تحفظيو ويو آهي.\nتمام وڪين ۾ ترجمو وجھڻ يا بدلائڻ لاءِ، مھرباني ڪري [https://translatewiki.net/ translatewiki.net] استعمال ڪريو، ميڊياوڪي جي لوڪلائيزيشڻ رٿا.",
        "namespaceprotected": "توهان کي نانءُپولار <strong>$1</strong> جا صفحا سنوارڻ جا اختيار ناهن.",
        "sitecssprotected": "اوهان وٽ ھن سيايسايس صفحي کي سنوارڻ جي اجازت ناھي، ڇو تہ ان سان سڀني گھمندڙ متاثر ٿي سگھن ٿا.",
        "mycustomcssprotected": "توهان کي هيءُ CSS صفحو سنوارڻ جي اجازت نہ آهي.",
        "password-name-match": "توهان جو ڳجھولفظ توهان جي واپرائيندڙ-نانءَ کان مختلف هجڻ لازمي آھي.",
        "mailmypassword": "ڳجھولفظ ٻيھر مقرر ڪريو",
        "passwordremindertitle": "{{SITENAME}} لاءِ نئون عارضي ڳجھولفظ",
-       "passwordremindertext": "ÚªÙ\86Ú¾Ù\86 (آءÙ\90Ù\8a Ù¾ØªÙ\8a $1 ØªØ§Ù\86) Ø§Ø³Ø§Ù\86 Ú©Ù\8a {{SITENAME}} ($4) Ù\84اءÙ\90 Ù\86ئÙ\88Ù\86 Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ Ø§Ù\85اڻڻ Ø¬Ù\8a Ú¯Ù\8fھرÙ\8e ÚªØ¦Ù\8a.\"$2\" Ù\88اپرائÙ\8aÙ\86دÚ\99 Ù\84اءÙ\90 Ú¾Úª Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ Ø³Ø±Ø¬Ù\8aÙ\88 Ù\88Ù\8aع Ø¢Ù\87Ù\8a \"$3\" ØªÙ\8a ØªØ±ØªÙ\8aب Ú\8fÙ\86Ù\88 Ù\88Ù\8aÙ\88 Ú¾Ù\88. Ø¬Ù\8aÚªÚ\8fÚ¾Ù\86 Ø§Ú¾Ù\88 ØªÙ\88ھاÙ\86 Ø¬Ù\88 Ø§Ø±Ø§Ø¯Ù\88 Ú¾Ù\8aÙ\88Ø\8c ØªÛ\81 Ú¾Ø§Ú»Ù\8a ØªÙ\88ھاÙ\86 Ú©Ù\8a Ú¾Ù\8aÙ\86ئر Ø¦Ù\8a Ø¯Ø§Ø®Ù\84 Ù¿Ù\8a Ù¾Ù\86Ú¾Ù\86جÙ\88 Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ ØªØ¨Ø¯Ù\8aÙ\84 ÚªØ±Ú» Ú¯Ú¾Ø±Ø¬Ù\8a.\nتÙ\88ھاÙ\86 Ø¬Ù\88 Ø¹Ø§Ø±Ø¶Ù\8a Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ {{PLURAL:$5|Ù\87Úª Ú\8fÙ\8aÙ\86Ú¾Ù\8fÙ\86|$5 Ú\8fÙ\8aÙ\86Ú¾Ù\8eÙ\86}} Û¾ Ø®ØªÙ\85 Ù¿Ù\8aÙ\86دÙ\88.\n\nجÙ\8aÚªÚ\8fÚ¾Ù\86 Ø§Ú¾Ø§ Ú¯Ù\8fھرÙ\8e Ø§Ù\88ھاÙ\86 Ù\86Û\81 ÚªØ¦Ù\8a Ú¾Ø¦Ù\8aØ\8c Ù\8aا Ú¾Ø§Ú»Ù\8a Ø§Ù\88ھاÙ\86 Ú©Ù\8a Ù¾Ù\86Ú¾Ù\86جÙ\88 Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ Ù\8aاد Ø§Ú\86Ù\8a Ù\88Ù\8aÙ\88 Ø¢Ú¾Ù\8a Û½ ØªÙ\88ھاÙ\86 Ø§Ù\86 Ú©Ù\8a ØªØ¨Ø¯Ù\8aÙ\84 ÚªØ±ڻ نٿا چاھيو، تہ توھان ھن نياپي کي نظر انداز ڪندي پنھنجو پراڻو ڳجھولفظ ئي استعمال ڪري سگھو ٿا.",
+       "passwordremindertext": "ÚªÙ\86Ú¾Ù\86 (آئÙ\90Ù¾Ù\8a Ù¾ØªÙ\8a $1 ØªØ§Ù\86) Ø§Ø³Ø§Ù\86 Ú©Ù\8a {{SITENAME}} ($4) Ù\84اءÙ\90 Ù\86ئÙ\88Ù\86 Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ Ø§Ù\85اڻڻ Ø¬Ù\8a Ú¯Ù\8fھرÙ\8e ÚªØ¦Ù\8a.\"$2\" Ù\88اپرائÙ\8aÙ\86دÚ\99 Ù\84اءÙ\90 Ú¾Úª Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ Ø³Ø±Ø¬Ù\8aÙ\88 Ù\88Ù\8aÙ\88 Ø¢Ù\87Ù\8a \"$3\" ØªÙ\8a ØªØ±ØªÙ\8aب Ú\8fÙ\86Ù\88 Ù\88Ù\8aÙ\88 Ú¾Ù\88. Ø¬Ù\8aÚªÚ\8fÚ¾Ù\86 Ø§Ú¾Ù\88 ØªÙ\88ھاÙ\86 Ø¬Ù\88 Ø§Ø±Ø§Ø¯Ù\88 Ú¾Ù\8aÙ\88Ø\8c ØªÛ\81 Ú¾Ø§Ú»Ù\8a ØªÙ\88ھاÙ\86 Ú©Ù\8a Ú¾Ù\8aÙ\86ئر Ø¦Ù\8a Ø¯Ø§Ø®Ù\84 Ù¿Ù\8a Ù¾Ù\86Ú¾Ù\86جÙ\88 Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ Ø¨Ø¯Ù\84ائڻ Ú¯Ú¾Ø±Ø¬Ù\8a.\nتÙ\88ھاÙ\86 Ø¬Ù\88 Ø¹Ø§Ø±Ø¶Ù\8a Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ {{PLURAL:$5|Ù\87Úª Ú\8fÙ\8aÙ\86Ú¾Ù\8fÙ\86|$5 Ú\8fÙ\8aÙ\86Ú¾Ù\8eÙ\86}} Û¾ Ø®ØªÙ\85 Ù¿Ù\8aÙ\86دÙ\88.\n\nجÙ\8aÚªÚ\8fÚ¾Ù\86 Ø§Ú¾Ø§ Ú¯Ù\8fھرÙ\8e Ø§Ù\88ھاÙ\86 Ù\86Û\81 ÚªØ¦Ù\8a Ú¾Ø¦Ù\8aØ\8c Ù\8aا Ú¾Ø§Ú»Ù\8a Ø§Ù\88ھاÙ\86 Ú©Ù\8a Ù¾Ù\86Ú¾Ù\86جÙ\88 Ú³Ø¬Ú¾Ù\88Ù\84Ù\81ظ Ù\8aاد Ø§Ú\86Ù\8a Ù\88Ù\8aÙ\88 Ø¢Ú¾Ù\8a Û½ ØªÙ\88ھاÙ\86 Ø§Ù\86 Ú©Ù\8a Ø¨Ø¯Ù\84ائڻ نٿا چاھيو، تہ توھان ھن نياپي کي نظر انداز ڪندي پنھنجو پراڻو ڳجھولفظ ئي استعمال ڪري سگھو ٿا.",
        "noemail": "واپرائيندڙ \"$1\" جو ڪو بہ برقٽپال پتو درج ٿيل ناهي.",
        "noemailcreate": "توھان کي قابلڪار برقٽپال پتو مھيا ڪرڻو پوندو.",
        "passwordsent": "واپرائيندڙ \"$1\" لاءِ ھڪ نئون ڳجھولفظ برقٽپال ذريعي اماڻيو ويو آهي.\nمھرباني ڪري اھو حاصل ڪرڻ بعد داخل ٿيندا.",
        "pt-userlogout": "خارج ٿيو",
        "php-mail-error-unknown": "پي ايڇ پي جي  ڪاڄ() اندر اڻڄاتل چُڪَ.",
        "user-mail-no-addy": "برقٽپال پتو ڄاڻائڻ کان سواءِ برقٽپال اماڻڻ جي ڪوشش ڪئي وئي.",
-       "changepassword": "ڳجھÙ\88Ù\84Ù\81ظ ØªØ¨Ø¯Ù\8aÙ\84 ÚªØ±يو",
+       "changepassword": "ڳجھÙ\88Ù\84Ù\81ظ Ø¨Ø¯Ù\84ايو",
        "resetpass_announce": "داخل ٿيڻ جو عمل پورو ڪرڻ لاءِ، توهان کي نئون ڳجھولفظ اختيار مقرر ڪرڻو پوندو.",
        "resetpass_header": "کاتي جو ڳجھولفظ بدلايو",
        "oldpassword": "اڳوڻو ڳجھولفظ:",
        "showdiff": "تبديليون ڏيکاريو",
        "blankarticle": "<strong>چِتاءُ:</strong> اوهان خالي صفحو سرجي رهيا آهيو.\nجيڪڏهن اوهان «$1» تي ٻيھر ڪلڪ ڪيو، تہ هي صفحو بغير ڪنھن مواد جي سرجيو ويندو.",
        "anoneditwarning": "<strong>چِتاءُ:</strong> توھان داخل ٿيل نہ آھيو. توھان جو آءِپي پتو عوامي طور ظاھر ٿيندو جي توھان ڪي سنوارون ڪريو ٿا. جيڪڏھن توھان <strong>[$1 داخل ٿيو]</strong> ٿا يا <strong>[$2 کاتو کوليو]</strong> ٿا، تہ ٻين فائدن سان گڏ توھان جون سنوارون توھان جي واپرائيندڙ-نانءَ سان منسوب ڪيون وينديون.",
-       "anonpreviewwarning": "توهان داخل ٿيل نہ آهيو. جيڪڏهن توهان صفحي ۾ تبديليون سانڍيون تہ اهڙين تبديلين ساڻ توهان جو آءِپي پتو درج ڪيو ويندو.",
-       "missingcommenttext": "براءِ مھرباني ڪو تاثر درج ڪندا.",
+       "anonpreviewwarning": "<em>توهان داخل ٿيل نہ آهيو. سانڍڻ سان توهان جو آئِپي پتو ھن صفحي جي سنوار سوانح ۾ درج ٿيندو.</em>",
+       "missingcommenttext": "مھرباني ڪري ڪو تاثر داخل ڪريو.",
        "summary-preview": "تت جي پيش نگاھ:",
        "subject-preview": "موضوع جي پيش نگاھ:",
        "blockedtitle": "واپرائيندڙ بندشيل آهي",
        "rev-deleted-event": "(لاگ تفصيل هٽايا ويا)",
        "rev-deleted-user-contribs": "[واپرائيندڙ-نانءُ يا آءِپِي پتو مِٽايو ويو - ڀاڱيدارين مان سنوار لڪائي وئي]",
        "rev-suppressed-no-diff": "توهان اهو تفاوت نٿا ڏسي سگھو، ڇاڪاڻ تہ ورجائن مان ڪو ھڪ <strong>ڊاھيو ويو آھي</strong>.",
-       "rev-delundel": "نمائش تبديل ڪريو",
+       "rev-delundel": "ظاھريت بدلايو",
        "rev-showdeleted": "ڏيکاريو",
        "revisiondelete": "ورجاءَ ڊاهيو/اڻ‌ڊاهيو",
        "revdelete-no-file": "ڄاڻايل فائيل وجود نٿو رکي.",
        "revdelete-failure": "ورجاءُ ظاھريت نہ جديدي سگھجي:\n$1",
        "logdelete-success": "لاگ ظاھريت مرتب ٿي.",
        "logdelete-failure": "لاگ ظاھريت مرتب نہ ٿي سگھجي:\n$1",
-       "revdel-restore": "نمائش تبديل ڪريو",
+       "revdel-restore": "ظاھريت بدلايو",
        "pagehist": "صفحي جي سوانح",
        "deletedhist": "ڊاٿل سوانح",
        "revdelete-otherreason": "ٻيا/اضافي ڪارڻ:",
        "prefs-editwatchlist-clear": "پنهنجي نظر ۾ فھرست ڊاهيو",
        "prefs-watchlist-days": "نظر ۾ فھرست ۾ ڏيکارڻ لاءِ ڏينهن:",
        "prefs-watchlist-days-max": "وڌ ۾ وڌ $1 {{PLURAL:$1|ڏينھن}}",
-       "prefs-watchlist-edits": "نظر ۾ فھرست ز۾ ڏيکارڻ جي لاءِ تبديلين جو وڌ-۾-وڌ انگ:",
+       "prefs-watchlist-edits": "نظر ۾ فھرست ۾ ڏيکارڻ جي لاءِ تبديلين جو وڌ-۾-وڌ انگ:",
        "prefs-watchlist-edits-max": "وڌ ۾ وڌ تعداد: 1000",
        "prefs-watchlist-token": "نظر ۾ فھرست جو ٽوڪن:",
        "prefs-misc": "متفرق",
        "searchresultshead": "ڳولا",
        "stub-threshold-sample-link": "نمونو",
        "stub-threshold-disabled": "اڻ-فعايل",
-       "recentchangesdays": "تازين تبديلين ۾ ڏيکارڻ جي لاءِ ڏينهن:",
+       "recentchangesdays": "تازين تبديلين ۾ ڏيکارڻ جي لاءِ ڏينھن:",
        "recentchangesdays-max": "وڌ ۾ وڌ $1 {{PLURAL:$1|ڏينهن}}",
-       "recentchangescount": "تازين تبديلين، صفحن جي سوانح، ۽ لاگس ۾ ڏيکارڻ لاءِ سنوارن جو خودڪار ڏنل انگ:",
+       "recentchangescount": "تازين تبديلين، صفحن جي سوانح، ۽ لاگس ۾ ڏيکارڻ لاءِ سنوارن جو ڏنل انگ:",
        "prefs-help-recentchangescount": "وڌ ۾ وڌ انگ: 1000",
        "savedprefs": "توھان جون ترجيحون سانڍجي چڪيون آھن.",
        "savedrights": "{{GENDER:$1|$1}} جا واپرائيندڙ گروھ سانڍجي چڪا آھن.",
        "yourrealname": "اصل نالو:",
        "yourlanguage": "ٻولي:",
        "yournick": "نئون دستخط",
-       "prefs-help-signature": "بحث ØµÙ\81Ø­Ù\8a ØªÙ\8a Ø±Ø§Ù\8aا Ú\8fÙ\8aÚ» Ù\88Ù\82ت Ù\87Ù\86 Ù\86شاÙ\86Ù\8aÙ\86 Ø°Ø±Ù\8aعÙ\8a \"<nowiki>~~~~</nowiki>\" Ø¯Ø³ØªØ®Ø· ÚªÙ\8aÙ\88Ø\8c Ø¬Ù\8aÚªÙ\8a Ù¾Ø§Ú»Ù\85رادÙ\88 ØªÙ\88Ù\87اÙ\86 Ø¬Ù\8a Ø¯Ø³ØªØ®Ø· Û½ Ù\88Ù\82ت Û¾ ØªØ¨Ø¯Ù\8aÙ\84 Ù¿ي ويندا.",
+       "prefs-help-signature": "بحث ØµÙ\81Ø­Ù\86 ØªÙ\8a Ø±Ø§Ù\8aا Ù\87Ù\86 \"<nowiki>~~~~</nowiki>\" Ø°Ø±Ù\8aعÙ\8a Ø¯Ø³ØªØ®Ø· ÚªØ±Ú» Ú¯Ú¾Ø±Ø¬Ù\86Ø\8c Ø¬Ù\8aÚªÙ\8a Ù¾Ø§Ú»Ù\85رادÙ\88 ØªÙ\88Ù\87اÙ\86 Ø¬Ù\8a Ø¯Ø³ØªØ®Ø· Û½ Ù\88Ù\82ت-ٺپÙ\8a Û¾ Ù\85ٽجي ويندا.",
        "badsiglength": "اهو درتخط هيڪاندو ڊگھو آهي.\nاها وڌ ۾ وڌ $1 {{PLURAL:$1|اکر|اکرن}} تي ٻڌل هجڻ گھرجي.",
        "yourgender": "توھان ڪيئن بيان ٿيڻ چاھيندا؟",
        "gender-unknown": "توهان جو ذڪر ڪندي، جيترو ٿي سگھيو، منطقگري بي جنس لفظن جو استعمال ڪندي.",
        "userrights-reason": "سبب:",
        "userrights-no-interwiki": "توهان کي ٻين وڪين تي واپرائيندڙ حق سنوارڻ جي اجازت ناھي.",
        "userrights-nodatabase": "اعداخانو $1 يا تہ وجود نٿو رکي يا تہ اهو مقامي اعدادخانو نہ آهي.",
-       "userrights-changeable-col": "گروپَ جيڪي توهان تبديل ڪري سگھو ٿا",
-       "userrights-unchangeable-col": "گروپَ جيڪي توهان تبديل نٿا ڪري سگھو",
+       "userrights-changeable-col": "گروھَ جيڪي توهان بدلائي سگھو ٿا",
+       "userrights-unchangeable-col": "گروھَ جيڪي توهان بدلائي نٿا سگھو",
        "userrights-irreversible-marker": "$1*",
        "userrights-no-shorten-expiry-marker": "$1#",
        "userrights-expiry-current": "مدو پورو $1",
        "userrights-expiry-options": "1 ڏينھن:1 ڏينھن،1 ھفتو:1 ھفتا،1 مھينو:1 مھينو،3 مھينا:3 مھينا،6 مھينا:6 مھينا،1 سال:1 سال",
        "group": "گروھ:",
        "group-user": "واپرائيندڙَ",
-       "group-autoconfirmed": "خودبخود پڪ ڪيل واپرائيندڙَ",
+       "group-autoconfirmed": "پاڻمرادو-پڪ-ڪيل واپرائيندڙَ",
        "group-bot": "بوٽس",
        "group-sysop": "منتظم",
        "group-interface-admin": "منتظم براءِ حليو",
        "action-editinterface": "واپرائيندڙ انٽرفيس سنواريو",
        "action-editusercss": "واپرائيندڙن جا سي.ايس.ايس فائيل سنواريو",
        "action-unblockself": "ڪنھن جي بندش ختم ڪريو",
-       "nchanges": "$1 {{PLURAL:$1|تبدÙ\8aÙ\84Ù\8a|تبدÙ\8aÙ\84Ù\8aÙ\88Ù\86}}",
+       "nchanges": "$1 {{PLURAL:$1|بدÙ\84اءÙ\8f|بدÙ\84اءÙ\8e}}",
        "ntimes": "$1ڀيرا",
        "enhancedrc-since-last-visit": "$1 {{PLURAL:$1|آخري ڦيري کان}}",
        "enhancedrc-history": "سوانح",
        "rcfilters-activefilters-show-tooltip": "سرگرم ڇاڻين جي ايراضي ڏيکاريو",
        "rcfilters-advancedfilters": "متقدم ڇاڻيون",
        "rcfilters-limit-title": "ڏيکارڻ لاءِ نتيجا",
-       "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|تبدÙ\8aÙ\84Ù\8a|$1 ØªØ¨Ø¯Ù\8aÙ\84Ù\8aÙ\88Ù\86}}، $2",
+       "rcfilters-limit-and-date-label": "$1 {{PLURAL:$1|بدÙ\84اءÙ\8f|$1 Ø¨Ø¯Ù\84اءÙ\8e}}، $2",
        "rcfilters-date-popup-title": "ڳولڻ لاءِ وقت جو دورانيو",
        "rcfilters-days-title": "ھاڻوڪا ڏينھن",
        "rcfilters-hours-title": "ھاڻوڪا ڪلاڪَ",
        "rcfilters-filter-logactions-label": "لاگڊ عمل",
        "rcfilters-filtergroup-lastrevision": "تازا-ترين ورجاءَ",
        "rcfilters-filter-lastrevision-label": "تازو-ترين ورجاءُ",
-       "rcfilters-filter-lastrevision-description": "ÚªÙ\86Ú¾Ù\86 ØµÙ\81Ø­Ù\8a Û¾ Ø±Ú³Ù\88 ØªØ§Ø²Ù\8a-ترÙ\8aÙ\86 ØªØ¨Ø¯Ù\8aÙ\84Ù\8a.",
+       "rcfilters-filter-lastrevision-description": "ÚªÙ\86Ú¾Ù\86 ØµÙ\81Ø­Ù\8a Û¾ Ø±Ú³Ù\88 ØªØ§Ø²Ù\88-ترÙ\8aÙ\86 Ø¨Ø¯Ù\84اءÙ\8f.",
        "rcfilters-filter-previousrevision-label": "تازو-ترين ورجاءُ نہ",
        "rcfilters-filter-previousrevision-description": "سڀ تبديليون جيڪي \"تازو-ترين ورجاءُ\" ناھن.",
        "rcfilters-tag-prefix-namespace-inverted": "<strong>:نہ</strong> $1",
        "rcfilters-watchlist-markseen-button": "سڀ تبديلين کي ڏٺل طور نشان لڳايو",
        "rcfilters-watchlist-edit-watchlist-button": "پنھنجي نظر ۾ صفحن جي فھرست سنواريو",
        "rcfilters-alldiscussions-label": "سڀ گفتگوئون",
-       "rcnotefrom": "Ù\87Ù\8aÙº {{PLURAL:$5|تبدÙ\8aÙ\84Ù\8a Ø¢Ù\87Ù\8a|تبدÙ\8aÙ\84Ù\8aÙ\88Ù\86 Ø¢Ù\87Ù\86}} Ú©Ø§Ù\86 <strong>$3, $4</strong> (تائين <strong>$1</strong> ) ڏيکاريل آهن.",
+       "rcnotefrom": "Ù\87Ù\8aÙº {{PLURAL:$5|بدÙ\84اءÙ\8f Ø¢Ù\87Ù\8a|بدÙ\84اءÙ\8e Ø¢Ù\87Ù\86}} Ú©Ø§Ù\86 <strong>$3Ø\8c $4</strong> (تائين <strong>$1</strong> ) ڏيکاريل آهن.",
        "rclistfromreset": "تاريخ چونڊڻ ٻيھر مرتب ڪريو",
        "rclistfrom": "$2، $3 کان شروع ٿيندڙ نيون تبديليون ڏيکاريو",
        "rcshowhideminor": "$1 معمولي سنوارون",
        "uploaded-hostile-svg": "چاڙھيل ايس.وي.جي فائيل جو غير محفوظ سي.ايس.ايس اسٽائيل ايلمينٽ ۾ مليو.",
        "uploaded-event-handler-on-svg": "ايس وي جي فائيل ۾ ايوينٽ هينڊلر خصوصيتون <code>$1=\"$2\"</code> مقرر ڪرڻ جي اجازت نہ آهي.",
        "uploaded-href-unsafe-target-svg": "href جو غير محفوظ ڊيٽا: يوآرآءِ نشانو مليو آهي <code>&lt;$1 $2=\"$3\"&gt;</code> چاڙھيل اَيسوِيجِي فائيل ۾",
-       "uploaded-animate-svg": "”اينيميٽ“ ٽيگ ڳوليو جيڪو ٿي سگھي ٿو href کي تبديل ڪري رهي هجي، چاڙھيل ايس.وي.جي فائيل ۾ \"form\" وصف استعمال ڪندي <code>&lt;$1 $2=\"$3\"&gt;</code>",
+       "uploaded-animate-svg": "”اينيميٽ“ ٽيگ لڌو جيڪو ٿي سگھي ٿو href کي بدلائي رهيو هجي، چاڙھيل ايسوِيجِي فائيل ۾ \"form\" وصف استعمال ڪندي <code>&lt;$1 $2=\"$3\"&gt;</code>",
        "uploaded-setting-event-handler-svg": "موقعو-سنڀاليندڙ جا انتساب ترتيبڻ بندشيل آهن، <code>&lt;$1 $2=\"$3\"&gt;</code> چاڙھيل ايس.وي.جي فائيل ۾ مليو",
        "uploaded-setting-href-svg": "\"set\"  ٽيگ کي \"href\" وصف استعمال ڪندي بنيادي عنصر کي بندشيو ويو آھي.",
        "uploaded-wrong-setting-svg": "\"set\" ٽيگ کي استعمال ڪندي رموٽ/ڊيٽا/اسڪرپٽ ٽارگيٽ کي ڪنھڻ وصف سان جوڙڻ کي بلاڪ ڪيو ويو آهي. \n<code>&lt;set to=\"$1\"&gt;</code> چاڙھيل ايس.وي.جي فائيل ۾ مليو آهي.",
        "randomincategory-submit": "هلو",
        "randomredirect": "بلاترتيب چورڻو",
        "statistics": "انگ-اکر",
-       "statistics-header-pages": "صفحي انگ اکر",
+       "statistics-header-pages": "صفحي انگ-اکر",
        "statistics-header-edits": "سنوار جا انگ-اکر",
-       "statistics-header-users": "واپرائيندڙن جا انگ اکر",
+       "statistics-header-users": "واپرائيندڙن جا انگ-اکر",
        "statistics-header-hooks": "ٻيا انگ-اکر",
        "statistics-articles": "موادي صفحا",
        "statistics-pages": "صفحا",
        "protectedpages-unknown-performer": "اڻڄاتل واپرائيندڙ",
        "protectedtitles": "تحفظيل عنوان",
        "protectedtitles-submit": "عنوان ڏيکاريو",
-       "listusers": "واپرائيندڙن جي فهرست",
+       "listusers": "واپرائيندڙن جي فھرست",
        "listusers-editsonly": "رڳو سنوارن وارا واپرائيندڙ ڏيکاريو",
        "listusers-temporarygroupsonly": "صرف عارضي واپرائيندڙ گروھن ۾ واپرائيندڙ ڏيکاريو",
        "listusers-creationsort": "سرجڻ جي تاريخ سان مرتب ڪريو",
        "unwatching": "نظر مان ڪڍندي...",
        "enotif_reset": "سڀ گھميل صفحن تي نشان لڳايو",
        "enotif_impersonal_salutation": "{{SITENAME}} واپرائيندڙ",
-       "enotif_lastdiff": "Ù\87Ù\8a ØªØ¨Ø¯Ù\8aÙ\84Ù\8a ڏسڻ لاءِ، $1 ڏسو",
+       "enotif_lastdiff": "Ù\87Ù\8a Ø¨Ø¯Ù\84اءÙ\8f ڏسڻ لاءِ، $1 ڏسو",
        "enotif_anon_editor": "گمنام واپرائيندڙ $1",
        "enotif_minoredit": "هيءَ ننڍڙي سنوار آهي",
        "created": "ٺهي چڪو",
-       "changed": "تبدÙ\8aÙ\84 Ù¿ي ويو",
+       "changed": "بدÙ\84جي ويو",
        "deletepage": "صفحو ڊاهيو",
        "confirm": "پڪ ڪريو",
        "delete-confirm": "\"$1\" ڊهي چڪو",
        "confirmdeletetext": "توهان هڪ صفحي کي ان جي سموري سوانح سميت ڊاهڻ وارا آهيو. مهرباني ڪري پڪ ڪندا ته توهان اهو ئي ڪرڻ گھرو ٿا، ۽ اهو ته توهان ان جي نتيجن کان واقف آهيو، ۽ اهو پڻ ته توهان اهو ڪم [[{{MediaWiki:Policy-url}}|پاليسي]]ءَ مطابق ڪري رهيا آهيو.",
        "actioncomplete": "ڪم پُورو",
        "actionfailed": "عمل ناڪام",
-       "deletedtext": "\"$1\" ڊهي چڪو آهي.\nتازو ڊاٺل صفحن جي فهرست لاءِ $2 ڏسندا.",
+       "deletedtext": "\"$1\" ڊھي چڪو آھي.\nتازين ڊاھن صفحن جي رڪارڊ لاءِ $2 ڏسو.",
        "dellogpage": "ڊاھ لاگ",
        "deletionlog": "ڊاٺ لاگ",
        "deletecomment": "سبب:",
        "logentry-contentmodel-change-revert": "واپس ورايو",
        "protectlogpage": "تحفظ لاگ",
        "protectedarticle": "محفوظ ٿيل \"[[$1]]\"",
-       "modifiedarticleprotection": "\"[[$1]]\" جي تحفظ جي سطح تبديل ڪئي",
+       "modifiedarticleprotection": "\"[[$1]]\" لاءِ تحفظي سطح بدلائي",
        "unprotectedarticle": "\"[[$1]]\" تان تحفظ ھٽايو ويو",
        "movedarticleprotection": "\"[[$2]]\" جو حفاظت درجو \"[[$1]]\" جي طرف منتقل ڪيو",
        "unprotectedarticle-comment": "\"[[$1]]\" تان {{GENDER:$2|تحفظ ھٽايو}}",
        "protect_expiry_invalid": "انجامي مدو ناقابلڪار آهي.",
        "protect_expiry_old": "انجامي مدو ماضيءَ ۾ آهي.",
        "protect-text": "توهان '''$1''' صفحي جي تحفظاتي سطح ڏسي ۽ بدلائي سگھو ٿا.",
-       "protect-locked-access": "تÙ\88Ù\87اÙ\86 Ø¬Ù\88 Ú©Ø§ØªÙ\88 ØµÙ\81Ø­Ù\86 Ø¬Ù\8a ØªØ­Ù\81ظاتÙ\8a Ø³Ø·Ø­ ØªØ¨Ø¯Ù\8aÙ\84Ù\8a ÚªØ±Ú» Ø¬Ø§ Ø§Ø®ØªÙ\8aار Ù\86Ù\87 Ù¿Ù\88 Ø±Ú©Ù\8a. Ù\87Ù\8aÙº ØµÙ\81Ø­Ù\8a Ø¬Ù\88Ù\86 Ù\88Ù\82Ù\88عات (سÙ\8aٽڱس) Ù¾Ù\8aØ´ ÚªØ¬Ù\86 Ù¿Ù\8aÙ\88Ù\86 '''$1''':",
+       "protect-locked-access": "تÙ\88Ù\87اÙ\86 Ø¬Ù\8a Ú©Ø§ØªÙ\8a Ú©Ù\8a ØµÙ\81Ø­Ù\86 Ø¬Ù\8a ØªØ­Ù\81ظ Ø³Ø·Ø­ Ø¨Ø¯Ù\84ائڻ Ø¬Ù\8a Ø§Ø¬Ø§Ø²Øª Ù\86Û\81 Ø¢Ú¾Ù\8a.\nھتÙ\8a ØµÙ\81Ø­Ù\8a Ù\84اءÙ\90 Ú¾Ø§Ú»Ù\88ÚªÙ\8aÙ\88Ù\86 ØªØ±ØªÙ\8aبÙ\88Ù\86 Ø¢Ú¾Ù\86 <strong>$1</strong>:",
        "protect-cascadeon": "هيءُ صفحو في الوقت تحفظيل آهي، ڇاڪاڻ ته اهو هيٺين {{PLURAL:$1|صفحي|صفحن}} جو حصو آهي، جنهن تي تحفظ در تحفظ لاڳو ٿيل آهي.\nChanges to this page's protection level will not affect the cascading protection.",
        "protect-default": "سڀ واپرائيندڙن کي اجازت ڏيو",
        "protect-fallback": "\"$1\" جي اجازت وارن واپرائيندڙن کي اجازت ڏيو",
        "unlockbtn": "اعدادخاني کي کوليو",
        "move-page": "$1 چوريو",
        "move-page-legend": "صفحو چوريو",
-       "movepagetext": "هيٺيون فارم استعمال ڪندي ڪنھن صفحي کي نئون عنوان ڏئي سگھجي ٿو، جنھن سان سمورو صفحو نئين عنوان ڏانھن هليو ويندو. \nاڳوڻو عنوان نئين عنوان ڏانھن چورڻو بڻجي ويندو. \nتوهان  چورڻن کي سنواري سگھو ٿا جيڪي اصل عنوان ڏانهن خودبخود اشارو ڪن ٿا.\nانهي ڳالھ جي پڪ ڪري وٺو تہ [[Special:BrokenRedirects|ٽٽل چورڻا]] يا [[Special:DoubleRedirects|ٻٽا چورڻا]] نہ هجن.\nان ڳالھ جي پڪ ڪرڻ ذميواري توهان تي آهي تہ ڳنڍڻا اتي ئي وٺي وڃن ٿا جتي انھن کي وٺي وڃڻ گھرجي.\n\nياد رکندا تہ جيڪڏهن نئين عنوان سان اڳي ئي ڪو مضمون موجود آهي ته پوءِ صفحو '''نہ''' چوريو ويندو، سواءِ ان جي تہ موجوده صفحو محظ خالي آهي يا ڪا بہ سوانح نہ رکندڙ ڪو چورڻو آهي.\n\n<strong>نوٽ!</strong>\nاها هڪ مقبول صفحي لاءِ ڪا غير متوقع ۽ انتھائي اڻوڻندڙ تبديلي ثابت ٿي سگھي ٿي؛ براءِ مھرباني اڳتي وڌڻ کان اڳ پڪ ڪندا تہ توهان اها تبديلي آڻڻ جي نتيجن کان چڱيءَ ريت واقف آهيو.",
-       "movepagetext-noredirectfixer": "هيٺيون فارم استعمال ڪندي ڪنھن صفحي کي نئون عنوان ڏئي سگھجي ٿو، جنھن سان سمورو صفحو نئين عنوان ڏانھن هليو ويندو. \nاڳوڻو عنوان نئين عنوان ڏانھن چورڻو بڻجي ويندو. \nتوهان  چورڻن کي سنواري سگھو ٿا جيڪي اصل عنوان ڏانھن خودبخود اشارو ڪن ٿا.\nانهي ڳالھ جي پڪ ڪري وٺو تہ [[Special:BrokenRedirects|ٽٽل چورڻا]] يا [[Special:DoubleRedirects|ٻٽا چورڻا]] نہ هجن.\nان ڳالھ جي پڪ ڪرڻ ذميواري توهان تي آهي تہ ڳنڍڻا اتي ئي وٺي وڃن ٿا جتي انھن کي وٺي وڃڻ گھرجي.\n\nياد رکندا تہ جيڪڏهن نئين عنوان سان اڳي ئي ڪو مضمون موجود آهي ته پوءِ صفحو '''نہ''' چوريو ويندو، سوا ان جي تہ موجوده صفحو محظ خالي آهي يا ڪا بہ سوانح نہ رکندڙ ڪو چورڻو آهي.\n\n<strong>نوٽ!</strong>\nاها هڪ مقبول صفحي لاءِ ڪا غير متوقع ۽ انتھائي اڻوڻندڙ تبديلي ثابت ٿي سگھي ٿي؛ مھرباني ڪري اڳتي وڌڻ کان اڳ پڪ ڪندا تہ توهان اها تبديلي آڻڻ جي نتيجن کان چڱيءَ ريت واقف آهيو.",
+       "movepagetext": "هيٺيون فارم استعمال ڪندي ڪنھن صفحي کي نئون عنوان ڏئي سگھجي ٿو، جنھن سان سمورو صفحو نئين عنوان ڏانھن هليو ويندو. \nاڳوڻو عنوان نئين عنوان ڏانھن چورڻو بڻجي ويندو. \nتوهان  چورڻن کي سنواري سگھو ٿا جيڪي اصل عنوان ڏانهن پاڻمرادو اشارو ڪن ٿا.\nانهي ڳالھ جي پڪ ڪري وٺو تہ [[Special:BrokenRedirects|ٽٽل چورڻا]] يا [[Special:DoubleRedirects|ٻٽا چورڻا]] نہ هجن.\nان ڳالھ جي پڪ ڪرڻ ذميواري توهان تي آهي تہ ڳنڍڻا اتي ئي وٺي وڃن ٿا جتي انھن کي وٺي وڃڻ گھرجي.\n\nياد رکندا تہ جيڪڏهن نئين عنوان سان اڳي ئي ڪو مضمون موجود آهي ته پوءِ صفحو '''نہ''' چوريو ويندو، سواءِ ان جي تہ موجوده صفحو محظ خالي آهي يا ڪا بہ سوانح نہ رکندڙ ڪو چورڻو آهي.\n\n<strong>نوٽ!</strong>\nاھو ھڪ مقبول صفحي لاءِ ڪو غير متوقع ۽ انتھائي اڻوڻندڙ بدلاءُ ثابت ٿي سگھي ٿو؛ مھرباني ڪري اڳتي وڌڻ کان اڳ پڪ ڪندا تہ توهان اھو بدلاءُ آڻڻ جي نتيجن کان چڱيءَ ريت واقف آهيو.",
+       "movepagetext-noredirectfixer": "هيٺيون فارم استعمال ڪندي ڪنھن صفحي کي نئون عنوان ڏئي سگھجي ٿو، جنھن سان سمورو صفحو نئين عنوان ڏانھن هليو ويندو. \nاڳوڻو عنوان نئين عنوان ڏانھن چورڻو بڻجي ويندو. \nتوهان  چورڻن کي سنواري سگھو ٿا جيڪي اصل عنوان ڏانھن پاڻمرادو اشارو ڪن ٿا.\nانهي ڳالھ جي پڪ ڪري وٺو تہ [[Special:BrokenRedirects|ٽٽل چورڻا]] يا [[Special:DoubleRedirects|ٻٽا چورڻا]] نہ هجن.\nان ڳالھ جي پڪ ڪرڻ ذميواري توهان تي آهي تہ ڳنڍڻا اتي ئي وٺي وڃن ٿا جتي انھن کي وٺي وڃڻ گھرجي.\n\nياد رکندا تہ جيڪڏهن نئين عنوان سان اڳي ئي ڪو مضمون موجود آهي ته پوءِ صفحو '''نہ''' چوريو ويندو، سوا ان جي تہ ھاڻوڪو صفحو محظ خالي آهي يا ڪا بہ سوانح نہ رکندڙ ڪو چورڻو آهي.\n\n<strong>نوٽ!</strong>\nاھو هڪ مقبول صفحي لاءِ ڪو غير متوقع ۽ انتھائي اڻوڻندڙ بدلاءُ ثابت ٿي سگھي ٿو؛ مھرباني ڪري اڳتي وڌڻ کان اڳ پڪ ڪندا تہ توهان اهو بدلاءُ آڻڻ جي نتيجن کان چڱيءَ ريت واقف آهيو.",
        "movepagetalktext": "جيڪڏهن توهان هن خاني کي نشان لڳائيندئو، واسطيدار مباحثي صفحو پاڻ ئي چوريو ويندو ماسواءِ اتي ڪو اڳ ئي ڪو غيرخالي مباحثي صفحو موجود هجي.\n\nان صورت ۾، جيڪڏهن توهان چاهيو ته صفحي کي پاڻ چوري يا ضم ڪري سگھو ٿا.",
        "movecategorypage-warning": "<strong>چتاءُ:</strong> اوهان زمري واري صفحي کي چورڻ وڃي رهيا آهيو. ياد رکو رڳو صفحو چرندو، پراڻي زمري ۾ ڪن بہ صفحن جي نئين صفحي ۾ ٻيھر-زمراڪاري <em>نہ</em> ڪئي ويندي.",
        "movenotallowed": "توهان کي صفحا چورڻ جي اجازت حاصل ڪانهي.",
        "tooltip-minoredit": "ھن کي هڪ معمولي سنوار طور نشان لڳايو",
        "tooltip-save": "پنھنجون تبديليون سانڍيو",
        "tooltip-publish": "پنهنجيون تبديليون ڇاپيو",
-       "tooltip-preview": "پنھنجي تبديلين تي نگاھ وجھو. براءِ مھرباني اھو سانڍڻ کان اڳ ڪندا.",
+       "tooltip-preview": "پنھنجي تبديلين تي نگاھ وجھو. مھرباني ڪري اھو سانڍڻ کان اڳ ڪندا.",
        "tooltip-diff": "لکت ۾ ڪيل پنھنجون تبديليون ڏسو",
        "tooltip-compareselectedversions": "هن صفحي جن وچ ۾ چونڊيل ورجائن وچ ۾ تفاوت ڏسو",
        "tooltip-watch": "هيءُ صفحو پنهنجي نظر ۾ فھرست ۾ شامل ڪريو",
        "confirm-watch-button": "ٺيڪ",
        "confirm-watch-top": "هيءُ صفحو پنهنجي نظر ۾ فھرست ۾ شامل ڪندا؟",
        "confirm-unwatch-button": "ٺيڪ",
-       "confirm-unwatch-top": "هيءُ صفحو پنهنجي نظر ۾ فهرست مان هٽائيندا؟",
+       "confirm-unwatch-top": "هيءُ صفحو پنھنجي نظر ۾ فھرست مان هٽائيندا؟",
        "confirm-rollback-top": "ھن صفحي ۾ ڪيل سنوارون واپس ورايون؟",
        "semicolon-separator": "؛&#32;",
        "comma-separator": "،&#32;",
        "watchlistedit-clear-titles": "عنوانَ:",
        "watchlisttools-clear": "نظر ۾ فھرست صاف ڪريو",
        "watchlisttools-view": "لاڳاپيل تبديليون ڏسو",
-       "watchlisttools-edit": "نظر ۾ فهرست ڏسو ۽ سنواريو",
+       "watchlisttools-edit": "نظر ۾ فھرست ڏسو ۽ سنواريو",
        "watchlisttools-raw": "ڪچي نظر ۾ فھرست سنواريو",
        "hijri-calendar-m1": "محرم",
        "hijri-calendar-m2": "صفر",
        "specialpages-group-media": "ميڊيا رپورٽ ۽ چاڙهيل",
        "specialpages-group-users": "واپرائيندڙَ ۽ حق",
        "specialpages-group-highuse": "وڌيڪ استعمال وارا صفحا",
-       "specialpages-group-pages": "صفحن جي فهرست",
+       "specialpages-group-pages": "صفحن جي فھرست",
        "specialpages-group-pagetools": "صفحن جا اوزار",
        "blankpage": "خالي صفحو",
        "intentionallyblankpage": "هيءُ صفحو ڄاڻي خالي ڇڏيو ويو آهي.",
        "tags-delete": "ڊاهيو",
        "tags-activate": "فعال بڻايو",
        "tags-deactivate": "غير فعال بڻايو",
-       "tags-hitcount": "$1 {{PLURAL:$1|تبدÙ\8aÙ\84Ù\8a|تبدÙ\8aÙ\84Ù\8aÙ\88Ù\86}}",
+       "tags-hitcount": "$1 {{PLURAL:$1|بدÙ\84اءÙ\8f|بدÙ\84اءÙ\8e}}",
        "tags-create-tag-name": "ٽيگ نانءُ:",
        "tags-create-reason": "سبب:",
        "tags-create-submit": "سرجيو",
        "htmlform-title-not-exists": "$1 وجود نٿو رکي.",
        "logentry-delete-delete": "$1 {{GENDER:$2|ڊاٿو}} صفحو $3",
        "logentry-delete-restore": "$1 {{GENDER:$2|بحاليو}} صفحو $3 ($4)",
-       "logentry-delete-revision": "$1 $3: $4 ØµÙ\81Ø­Ù\8a ØªÙ\8a {{PLURAL:$5|Ú¾Úª Ù\88رجاءÙ\8e|$5 Ù\88رجائÙ\86}} Ø¬Ù\8a Ø¸Ø§Ú¾Ø±Ù\8aت {{GENDER:$2|تبدÙ\8aÙ\84 Úªئي}}",
+       "logentry-delete-revision": "$1 $3: $4 ØµÙ\81Ø­Ù\8a ØªÙ\8a {{PLURAL:$5|Ú¾Úª Ù\88رجاءÙ\8e|$5 Ù\88رجائÙ\86}} Ø¬Ù\8a Ø¸Ø§Ú¾Ø±Ù\8aت {{GENDER:$2|بدÙ\84ائي}}",
        "revdelete-content-hid": "مواد لڪيل",
        "revdelete-uname-hid": "واپرائيندڙ-نانءُ لڪل",
        "revdelete-unrestricted": "منتظمن تان پابنديون ھٽايون ويون",
index a4c30f8..fc3c4f3 100644 (file)
@@ -67,6 +67,7 @@
        "tog-useeditwarning": "Upozori me kad napuštam stranicu za uređivanje bez snimanja izmjena",
        "tog-prefershttps": "Uvijek koristi sigurnu vezu dok sam prijavljen",
        "tog-showrollbackconfirmation": "Prikaži potvrdnicu kada kliknete vezu za opoziv",
+       "tog-requireemail": "Zahtijevaj e-poštu za stavljanje novu lozinku",
        "underline-always": "Uvijek",
        "underline-never": "Nikad",
        "underline-default": "prema skinu ili postavkama preglednika",
        "undo-norev": "Izmjena se ne može vratiti jer ne postoji ranija ili je obrisana.",
        "undo-nochange": "Ovo je uređivanje izgleda već bilo poništeno.",
        "undo-summary": "Poništena izmjena $1 [[Special:Contribs/$2|korisnika $2]] ([[User talk:$2|razgovor]])",
+       "undo-summary-anon": "Poništi izmjenu $1 {{GENDER:$2|korisnika|korisnice}} [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Poništi izmjenu $1 od skrivenog korisnika",
        "cantcreateaccount-text": "Pravljenje korisničkog računa sa ove IP adrese ('''$1''') je blokirano od strane [[User:$3|$3]].\n\nRazlog koji je naveo $3 je ''$2''",
        "cantcreateaccount-range-text": "Stvaranje računa od IP adresa iz pojasa<strong>$1</strong>, koji uključuje vašu IP adresu (<strong>$4</strong>), je blokirao/la [[User:$3|$3]].\n\nRazlog koji je dao/la $3 je <em>$2</em>",
        "prefs-help-email": "E-mail adresa je opcionalna, ali je potrebna jer omogućava da Vam se pošalje nova šifra u slučaju da je izgubite ili zaboravite.",
        "prefs-help-email-others": "Također možete da odaberete da vas drugi kontaktiraju putem vaše korisničke stranice ili stranice za razgovor bez otkrivanja vašeg identiteta.",
        "prefs-help-email-required": "Neophodno je navesti e-mail adresu.",
+       "prefs-help-requireemail": "Ako je štiklirano, mogućnost za novu lozinku će imaju samo korisnici koji naveli su korisničko ime i e-poštu.",
        "prefs-info": "Osnovne informacije",
        "prefs-i18n": "Internacionalizacija",
        "prefs-signature": "Potpis",
        "alreadyrolled": "Ne može se vratiti posljednja izmjena [[:$1]] od korisnika [[User:$2|$2]] ([[User talk:$2|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]); neko drugi je već izmjenio ili vratio članak.\n\nPosljednja izmjena je bila od korisnika [[User:$3|$3]] ([[User talk:$3|razgovor]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Sažetak izmjene je bio: <em>$1</em>.",
        "revertpage": "Vraćene izmjene [[Special:Contributions/$2|$2]] ([[User talk:$2|razgovor]]) na posljednju izmjenu korisnika [[User:$1|$1]]",
+       "revertpage-anon": "Vraćene izmjene [[Special:Contributions/$2|$2]] na posljednju izmjenu korisnika [[User:$1|$1]]",
        "revertpage-nouser": "Vraćene izmjene skrivenog korisnika na posljednju reviziju, koju je {{GENDER:$1|napravio|napravila}} [[User:$1|$1]]",
        "rollback-success": "Vraćene su izmjene korisnika {{GENDER:$3|$1}};\nvraćeno na posljednju verziju koju je snimio {{GENDER:$4|$2}}.",
        "sessionfailure-title": "Greška u sesiji",
        "ipblocklist-legend": "Traži blokiranog korisnika",
        "blocklist-userblocks": "Sakrij blokade računa",
        "blocklist-tempblocks": "Sakrij privremene blokade",
+       "blocklist-indefblocks": "Sakrij beskonačne blokade",
        "blocklist-addressblocks": "Sakrij pojedinačne IP blokade",
        "blocklist-type": "Vrsta:",
        "blocklist-type-opt-all": "Sve",
index cd4e8dd..10882ad 100644 (file)
@@ -71,7 +71,7 @@
        "tog-shownumberswatching": "Zobraziť počet používateľov sledujúcich stránku",
        "tog-oldsig": "Váš súčasný podpis:",
        "tog-fancysig": "Považovať podpisy za wikitext (bez automatických odkazov)",
-       "tog-uselivepreview": "Používať živý náhľad",
+       "tog-uselivepreview": "Zobrazovať náhľady bez obnovenia stránky",
        "tog-forceeditsummary": "Upozoriť ma, keď nevyplním zhrnutie úprav",
        "tog-watchlisthideown": "Skryť moje úpravy zo zoznamu sledovaných",
        "tog-watchlisthidebots": "Skryť úpravy botov zo zoznamu sledovaných",
        "createacct-another-submit": "Vytvoriť účet",
        "createacct-continue-submit": "Pokračovať vo vytváraní účtu",
        "createacct-another-continue-submit": "Pokračovať vo vytváraní účtu",
-       "createacct-benefit-heading": "{{GRAMMAR:akuzatív|{{SITENAME}}}} tvoria ľudia ako ste vy.",
+       "createacct-benefit-heading": "{{GRAMMAR:akuzatív|{{SITENAME}}}} tvoria ľudia ako vy.",
        "createacct-benefit-body1": "{{PLURAL:$1|úprava|úpravy|úprav}}",
        "createacct-benefit-body2": "{{PLURAL:$1|stránka|stránky|stránok}}",
        "createacct-benefit-body3": "{{PLURAL:$1|nedávny prispievateľ|nedávni prispievatelia|nedávnych prispievateľov}}",
        "rcfilters-empty-filter": "Žiadne aktívne filtre. Všetky príspevky sú zobrazené.",
        "rcfilters-filterlist-title": "Filtre",
        "rcfilters-filterlist-whatsthis": "Ako to funguje?",
-       "rcfilters-filterlist-feedbacklink": "Povedzte nám, čo si myslíte o týchto (nových) filtroch",
+       "rcfilters-filterlist-feedbacklink": "Povedzte nám, čo si myslíte o týchto filtroch",
        "rcfilters-highlightbutton-title": "Zvýrazniť výsledky",
        "rcfilters-highlightmenu-title": "Vybrať farbu",
        "rcfilters-highlightmenu-help": "Vyberte farbu pre zvýraznenie tejto vlastnosti",
index 7cd6220..9a40d38 100644 (file)
@@ -64,6 +64,7 @@
        "tog-useeditwarning": "Opozori me, ko skušam zapreti urejevalno polje z neshranjenimi spremembami",
        "tog-prefershttps": "Med prijavo vedno uporabljaj varno povezavo",
        "tog-showrollbackconfirmation": "Pokaži potrditveno okno ob kliku na povezavo za vrnitev",
+       "tog-requireemail": "Zahtevaj e-poštni naslov za ponastavitev gesla",
        "underline-always": "Vedno",
        "underline-never": "Nikoli",
        "underline-default": "Koža ali privzeto v brskalniku",
        "undo-norev": "Urejanja ni mogoče razveljaviti, ker ne obstaja ali je bilo izbrisano.",
        "undo-nochange": "Zdi se, da je urejanje nekdo že razveljavil.",
        "undo-summary": "Redakcija $1 uporabnika [[Special:Contributions/$2|$2]] ([[User talk:$2|pogovor]]) razveljavljena",
+       "undo-summary-anon": "Razveljavitev redakcije $1 uporabnika [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Razveljavi redakcijo $1 skritega uporabnika",
        "cantcreateaccount-text": "Registracije z IP-naslova ('''$1''') je administrator(ka) [[User:$3|$3]] blokiral(a).\n\nRazlog, ki ga je $3 podal(a), je ''$2''.",
        "cantcreateaccount-range-text": "Ustvarjanje računov z IP-naslovov v območju <strong>$1</strong>, ki vključuje vaš IP-naslov (<strong>$4</strong>), je blokiral(-a) [[User:$3|$3]].\n\nRazlog, ki ga je podal(-a) $3, je <em>$2</em>.",
        "prefs-help-email": "E-poštni naslov ni obvezen, vendar omogoča, da vam v primeru pozabljenega gesla pošljemo novo.",
        "prefs-help-email-others": "Omogočite lahko tudi možnost, da vam lahko ostali uporabniki pošiljajo e-pošto prek vaše uporabniške ali pogovorne strani.\nKo vas drugi uporabniki kontaktirajo, jim vašega e-poštnega naslova ne bomo razkrili.",
        "prefs-help-email-required": "E-poštni naslov je obvezen.",
+       "prefs-help-requireemail": "Če je označeno, bo e-pošta za ponastavitev gesla poslana samo, če je oseba, ki je sprožila ponastavitev, vnesla tako uporabniško ime kot e-poštni naslov tega računa.",
        "prefs-info": "Osnovni podatki",
        "prefs-i18n": "Internacionalizacija",
        "prefs-signature": "Podpis",
        "alreadyrolled": "Zadnje spremembe [[:$1]] uporabnika [[User:$2|$2]] ([[User talk:$2|pogovor]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) ne morem vrniti;\nstran je spremenil ali vrnil že nekdo drug.\n\nZadnji je stran urejal uporabnik [[User:$3|$3]] ([[User talk:$3|pogovor]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Povzetek urejanja je bil: <em>$1</em>.",
        "revertpage": "vrnitev sprememb uporabnika [[Special:Contributions/$2|$2]] ([[User talk:$2|pogovor]]) na zadnje urejanje uporabnika [[User:$1|$1]]",
+       "revertpage-anon": "Vrnjena urejanja uporabnika [[Special:Contributions/$2|$2]] na zadnjo redakcijo uporabnika [[User:$1|$1]]",
        "revertpage-nouser": "vrnitev sprememb skritega uporabnika na zadnjo redakcijo {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Razveljavljene spremembe {{GENDER:$3|uporabnika|uporabnice}} $1;\nvrnjeno na urejanje {{GENDER:$4|uporabnika|uporabnice}} $2.",
        "sessionfailure-title": "Neuspeh seje",
index 5fe33ce..7dd965f 100644 (file)
        "tog-useeditwarning": "Varna mig om jag lämnar en redigeringssida med osparade ändringar",
        "tog-prefershttps": "Använd alltid en säker anslutning medan jag är inloggad",
        "tog-showrollbackconfirmation": "Visa en bekräftelsedialog när man klickar på en tillbakarullningslänk",
+       "tog-requireemail": "Kräv e-postadress för att återställa lösenord",
        "underline-always": "Alltid",
        "underline-never": "Aldrig",
        "underline-default": "Webbläsarens eller utseendets standardinställning",
        "undo-norev": "Redigeringen kan inte göras ogjord eftersom den inte finns eller har raderats.",
        "undo-nochange": "Det verkar som att redigeringen redan har blivit ogjord.",
        "undo-summary": "Gör version $1 av [[Special:Contributions/$2|$2]] ([[User talk:$2|diskussion]]) ogjord",
+       "undo-summary-anon": "Ångra sidversionen $1 av [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Gör version $1 av en dold användare ogjord",
        "cantcreateaccount-text": "[[User:$3|$3]] har blockerat den här IP-adressen ('''$1''') från att registrera konton.\n\nAnledningen till blockeringen var \"$2\".",
        "cantcreateaccount-range-text": "IP-adresserna i intervallet <strong>$1</strong>, som inkluderar din IP-adress (<strong>$4</strong>), har blockerats från att skapa konton av [[User:$3|$3]].\n\nAnledningen enligt $3 var <em>$2</em>",
        "prefs-help-email": "Att ange e-postadress är valfritt, men gör det möjligt att få ditt lösenord mejlat till dig om du glömmer det.",
        "prefs-help-email-others": "Du kan också välja att låta andra kontakta dig via e-post genom en länk på din användar- eller diskussionssida. \nDin e-postadress avslöjas inte när andra användare kontaktar dig.",
        "prefs-help-email-required": "E-postadress måste anges.",
+       "prefs-help-requireemail": "Om detta markeras kommer lösenordsåterställningar endast skickas via e-post om återställaren har angivit både användarnamn och e-postadress för detta konto.",
        "prefs-info": "Grundläggande information",
        "prefs-i18n": "Internationalisering",
        "prefs-signature": "Signatur",
        "alreadyrolled": "Det gick inte att rulla tillbaka den senaste redigeringen av [[User:$2|$2]] ([[User talk:$2|diskussion]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]) på sidan [[:$1|$1]]. Någon annan har redan rullat tillbaka eller redigerat sidan.\n\nSidan ändrades senast av [[User:$3|$3]] ([[User talk:$3|diskussion]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]).",
        "editcomment": "Redigeringskommentaren var: <em>$1</em>.",
        "revertpage": "Återställde redigeringar av  [[Special:Contributions/$2|$2]] ([[User talk:$2|användardiskussion]]) till senaste versionen av [[User:$1|$1]]",
+       "revertpage-anon": "Ångrade redigeringar av [[Special:Contributions/$2|$2]] till senaste sidversionen av [[User:$1|$1]]",
        "revertpage-nouser": "Återställde redigeringar av en dold användare till den senaste versionen av {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Återställde ändringar av {{GENDER:$3|$1}};\nändrade tillbaka till senaste versionen av {{GENDER:$4|$2}}.",
        "sessionfailure-title": "Sessionsfel",
index 8a7289f..31492ed 100644 (file)
        "morenotlisted": "Ńy je to kůmplytno lista",
        "mypage": "Zajta",
        "mytalk": "Dyskusyjŏ",
-       "anontalk": "Godka tygo IP",
+       "anontalk": "Dyskusyjŏ",
        "navigation": "Nawigacyjŏ",
        "and": "&#32;i",
        "faq": "FAQ",
        "viewsourcelink": "pokŏż zdrzōdło",
        "editsectionhint": "Edytuj sekcyjõ: $1",
        "toc": "Wykŏz treści",
-       "showtoc": "uobejrzij",
-       "hidetoc": "schrůń",
+       "showtoc": "pokŏż",
+       "hidetoc": "skryj",
        "collapsible-collapse": "Skryj",
        "collapsible-expand": "Pokŏż",
        "thisisdeleted": "Pokŏzać abo stworzić zaś $1?",
        "sort-ascending": "Sortuj rosnůnco",
        "nstab-main": "Strōna",
        "nstab-user": "{{GENDER:{{BASEPAGENAME}}|Strōna ôd używŏcza|Strōna ôd używŏczki}}",
-       "nstab-media": "Pliki",
+       "nstab-media": "Zbiōr",
        "nstab-special": "Specjalnŏ strōna",
        "nstab-project": "Strōna projektu",
        "nstab-image": "Zbiōr",
        "filereadonlyerror": "Ńy idźe pomjyńać plika \"$1\" abo repozytorjum \"$2\" terozki je zawarte.\n\nAdministrator kery zawarł wćepał kůmyntorz: \"$3\".",
        "invalidtitle-knownnamespace": "Felerne mjano \"$3\" w przestrzeńy \"$2\".",
        "invalidtitle-unknownnamespace": "Felerne mjano ze ńyznomům nůmerům raumu mjan $1: \"$2\"",
-       "exception-nologin": "Ńy jest żeś zalogůwany",
+       "exception-nologin": "Niy je żeś wlogowany(ŏ)",
        "exception-nologin-text": "Prosza [[Special:Userlogin|zaloguj śe]] coby mjeć mogebność przejśćo do tyj zajty abo akcyji.",
        "virus-badscanner": "Felerno konfiguracyjo – ńyznany skaner antywirusowy ''$1''",
        "virus-scanfailed": "skanowańy ńyudone (feler $1)",
        "changepassword-success": "Twoje hasło zostoło půmyślńy půmjyńone!",
        "botpasswords": "Hasła bota",
        "resetpass_forbidden": "Ńy idźe sam půmjyńyć hasłůw.",
-       "resetpass-no-info": "Muśisz być zalogowany, coby uzyskoć bezpostrzedńi dostymp do tyj zajty.",
+       "resetpass-no-info": "Żeby mieć bezpostrzedni dostymp do tyj strōny, trzeba sie zalogować.",
        "resetpass-submit-loggedin": "Zmjyń hasło",
        "resetpass-submit-cancel": "Uodćepej",
        "resetpass-wrong-oldpass": "Felerne tymczasowe abo aktualne hasło.\nMożliwe co właśńy zmjyńiłżeś swoje hasło abo poprosiłżeś uo nowe tymczasowe hasło.",
        "changeemail-newemail": "Nowŏ e-mailowŏ adresa:",
        "changeemail-none": "podstawowo",
        "changeemail-submit": "Spamjyntej nowy",
-       "resettokens": "Resetuj tokeny",
+       "resettokens": "Resetuj tokyny",
        "bold_sample": "Ruby tekst",
        "bold_tip": "Ruby tekst",
        "italic_sample": "Kursywa",
        "watchthis": "Ôbserwuj tã strōnã",
        "savearticle": "Spamiyntej",
        "publishpage": "Ôpublikuj strōnã",
+       "publishchanges": "Ôpublikuj zmiany",
        "publishpage-start": "Ôpublikuj strōnã...",
        "preview": "Podglōnd",
        "showpreview": "Pokŏż podglōnd",
        "showdiff": "Pokŏż zmiany",
        "anoneditwarning": "<strong>Pozōr:</strong> Niy je żeś wlogowany(ŏ). Jak zrobisz jakeś zmiany, to Twoja adresa IP bydzie publicznie widać. Jeźli <strong>[$1 sie wlogujesz]</strong> abo <strong>[$2 stworzisz kōnto]</strong>, to Twoje zmiany bydōm przipisane do kōnta społym ze inkszymi profitami.",
-       "anonpreviewwarning": "Ńy jeżeś zalogowany. Twój IP ausdruk uostańy spamjyntany, eli ty bydźesz sprowjać zajte.",
+       "anonpreviewwarning": "<em>Niy je żeś wlogowany(ŏ). Spamiyntanie zmian zapisze twoja adresa IP we historyji edycyji tyj strōny.</em>",
        "missingsummary": "'''Pozůr:''' Ńy wprowadźůł żeś uopisu pomjyńań. Kej go ńy chcesz wprowadzać, naćiś knefel Spamjyntej jeszcze roz.",
        "missingcommenttext": "Wkludź kōmyntŏrz niżyj.",
        "missingcommentheader": "'''Dej pozůr:''' Treść nagłůwka je blank - uzupełńij go! Jeli tego ńy zrobisz, Twůj kůmyntorz bydźe naszkryflony bez nagłůwka.",
        "editingold": "'''Dej pozůr: Sprowjosz inkszo wersyjo zajty kej bjeżůnco. Jeli jům naszkryflosz, wszyjske půźńyjsze pomjyńańa bydům wyćepane.'''",
        "yourdiff": "Rōżnice",
        "copyrightwarning": "Pamjyntej uo tym, aże cołki wkłod do {{SITENAME}} udostympńůmy wedle zasad $2 (dokładńij we $1). Jak ńy chcesz, coby kożdy můg go půmjyńać a dalij rozpowszychńoć, ńy wćepuj uůnygo sam. Szkryflajůnc sam tukej pośwjadczosz tyż, co te pisańy je twoje własne, abo żeś go wźůn(a) ze materjołůw kere sům na ''public domain'', abo kůmpatybilne.<br />\n'''PROSZA ŃY WĆEPYWAĆ SAM MATYRJOŁŮW KERE SŮM CHRŮŃONE AUTORSKIM PRAWYM BEZ DOZWOLEŃO WŁAŚĆIĆELA!'''",
-       "copyrightwarning2": "Pamjyntej uo tym, aże cołki wkłod do {{GRAMMAR:MS.lp|{{SITENAME}}}} może być sprowjany, pomjyńany abo wyćepany bez inkszych użytkownikůw. Jak ńy chcysz, coby kożdy můg uůnygo zmjyńać a dalij rozpowszychńoć bez uograniczyń, ńy wćepuj go sam.<br />\nSzkryflajůnc sam tukej pośwjadczosz tyż, co te pisańy je twoje własne, abo żeś go wźůn(a) ze matyrjołůw kere sům na public domain, abo kůmpatybilne (kuknij tyż: $1).\n'''PROSZA ŃY WĆEPYWAĆ SAM MATYRJOŁŮW KERE SŮM CHRŮŃONE PRAWYM AUTORSKIM BEZ DOZWOLEŃO WŁAŚĆIĆELA!'''",
+       "copyrightwarning2": "Dej pozōr, iże cołki wkłŏd na {{SITENAME}} może być edytowany, zmiyniany abo kasowany ôd inkszych używŏczōw. Jeźli niy chcesz, żeby twōj tekst bōł niymiyłosiernie edytowany, to niy wkludzej go sam.<br />\nPrzirzekŏsz tyż nōm, iże wszyjsko je napisane ôd ciebie abo skopiowane ze dōmyny publicznyj abo podobnego wolnego zdrzōdła (po wiyncyj informacyji patrz $1).\n<strong>Niy wkludzej dzieł chrōniōnych autorskimi prawami bez przizwolyniŏ!</strong>",
        "longpageerror": "''Feler: Tekst kery żeś sam wćepywoł mo {{PLURAL:$1|jedyn kilobajt|$1 kilobajtůw}}. Maksymalno dugość tekstu ńy może być srogszo kej {{PLURAL:$2|jedyn kilobajt|$2 kilobajtůw}}. Twůj tekst ńy bydźe sam naszkryflany.'''",
        "readonlywarning": "'''Dej pozůr: Baza danych zostoua filowo zawarto skuli potřeb admińistracyjnych. Bestůž ńy do śe terozki naškryflać Twojich pomjyńań. Radzymy přećepać nowy tekst kajś do plika tekstowego (wytnij/wklej) a wćepać sam zaś po uodymkńyńću bazy.'''\n\nAdmińistrator kery zawar baza dou take wyjaśńyńe: $1",
        "protectedpagewarning": "'''Dej pozůr: Sprowjańe tyj zajty zostoło zawarte. Mogům jům sprowjać ino użytkowńicy ze uprawńyńami admińistratora.'''\nUostatńy wpis w rejerze je poniżej.",
-       "semiprotectedpagewarning": "'''Pozůr:''' Ta zajta zostoÅ\82a zawarto a ino zaregiszterowani użytkownicy mogům jům sprowjaÄ\87.\nUostotÅ\84y wpis w rejerze je Å\84yżej.",
+       "semiprotectedpagewarning": "'''PozÅ\8dr:''' Ta strÅ\8dna je zawartÅ\8f i ino zaregistrowani używÅ\8fcze mogÅ\8dm jÅ\8dm edytowaÄ\87.\nÃ\94statni wpis ze regestu je niżyj.",
        "cascadeprotectedwarning": "'''Dej pozůr:''' Ta zajta zostoła zawarto a ino użytkowńicy ze uprawńyńami admińistratora mogům jům sprowjać. Zajta ta je podpjynto pod {{PLURAL:$1|nastympujůnco zajta, kero zostoła zawarto|nastympujůncych zajtach, kere zostouy zawarte}} ze załůnczonům uopcjům dźedźiczyńo:",
        "titleprotectedwarning": "'''Dej pozůr: Zajta uo tym titlu zostoła zawarto a ino [[Special:ListGroupRights|ńykerzi użytkowńicy]] mogům jům wćepać.'''\nUostatńy wpis z rejera je ńyżej.",
        "templatesused": "{{PLURAL:$1|Muster użyty|Mustry użyte}} na tyj strōnie:",
-       "templatesusedpreview": "{{PLURAL:$1|Muster użyty|Mustry użyte}} na tyj podglōńdzie:",
+       "templatesusedpreview": "{{PLURAL:$1|Muster użyty|Mustry użyte}} na tym podglōńdzie:",
        "templatesusedsection": "{{PLURAL:$1|Szablon|Szablůny}} użyte we tyj tajli:",
        "template-protected": "(chrōniōny)",
        "template-semiprotected": "(pōłzawarte)",
        "permissionserrorstext-withaction": "Niy mŏsz przizwolyniŏ na $2, skuli {{PLURAL:$1|takigo powodu|takich powodōw}}:",
        "recreate-moveddeleted-warn": "<strong>Pozōr: Prziwrŏcŏsz strōnã, co była przōdzij skasowanŏ.</strong>\n\nDej pozōr, czy prziwrōcynie tyj strōny je nŏleżne.\nRegesty kasowań i pōnkniyńć tyj strōny idzie ôbejzdrzeć niżyj.",
        "moveddeleted-notice": "Ta strōna była skasowanŏ.\nRegest skasowań, zabezpieczyń i pōnkniyńć tyj strōny je pokŏzany niżyj.",
-       "log-fulllog": "Ukoż rejer",
+       "log-fulllog": "Pokoż cołki regest",
        "edit-hook-aborted": "Sprowjyńy sztopńynte skiż hoka.\nŃy je wjadůme pů jakymu.",
        "edit-gone-missing": "Ńy idźe zaktualizować zajty.\nZdowo śe, co zostoła wyćepano.",
        "edit-conflict": "Kůnflikt sprowjyń.",
        "edit-no-change": "Twoje sprowjyńe uostoło zignorowane pů takymu, aże ńic żeś we tekśće ńy zmjyńůł.",
        "postedit-confirmation-saved": "Spamjyntano twoje sprowjyńe.",
        "edit-already-exists": "Ńy idźe utworzić nowyj zajty.\nTako zajta już sam je.",
-       "defaultmessagetext": "Tekst důmyślny",
+       "defaultmessagetext": "Wychodny tekst wiadōmości",
        "content-model-wikitext": "wikitekst",
        "expensive-parserfunction-warning": "Dej pozůr: ta zajta mo za dużo uodwouań do funkcyji parsera, kere mocno uobćůnżajům systym.\n\nPowinno być myńi jak $2 {{PLURAL:$2|wywołańy|wywołańo|wywołań}}, a terozki {{PLURAL:$1|je $1 wywołańy|sům $1 wywołańo|je $1 wywołań}}.",
        "expensive-parserfunction-category": "Zajty kere majům za dużo uodwołań do funkcyji parsera, kere mocno uobćůnżajům systym.",
        "search-showingresults": "{{PLURAL:$4|Rezultat <strong>$1</strong> ze <strong>$3</strong>|Rezultaty <strong>$1 – $2</strong> ze <strong>$3</strong>}}",
        "search-nonefound": "Żŏdne wyniki niy ôdpowiadajōm tymu zapytaniu.",
        "powersearch-legend": "Sznupańy zaawansowane",
-       "powersearch-ns": "Sznupej we przestrzyńach mjan:",
+       "powersearch-ns": "Szukej we przestrzyniach mian:",
        "powersearch-togglelabel": "Ôznŏcz:",
        "powersearch-toggleall": "Wszyjsko",
        "powersearch-togglenone": "Nic",
        "prefs-edits": "Liczba edycyji:",
        "prefs-skin": "Skůrka",
        "skin-preview": "podglůnd",
-       "datedefault": "Důmyślny",
+       "datedefault": "Wychodny",
        "prefs-labs": "Funkcyje \"labs\"",
        "prefs-user-pages": "Zajty ôd używŏczōw",
        "prefs-personal": "Dane używocza",
        "prefs-rc": "Ôstatnie zmiany",
-       "prefs-watchlist": "Pozůrlista",
+       "prefs-watchlist": "Ôbserwowane",
        "prefs-watchlist-days": "Liczba dńůw widocznych na liśće artikli, na kere dowosz pozůr:",
        "prefs-watchlist-days-max": "Max $1 {{PLURAL:$1|dźyń|dńi}}",
        "prefs-watchlist-edits": "Liczba půmjyńań pokozywanych we rozszyrzůnyj liśće artiklůw, na kere dowosz pozůr:",
        "recentchangesdays": "Liczba dńůw do pokazańo we půmjyńanych na uostatku:",
        "recentchangesdays-max": "(maksymalńy $1 {{PLURAL:$1|dźyń|dńi}})",
        "recentchangescount": "Liczba pozycyji na liśće půmjyńanych na uostatku, we historyje zajtůw a zajtach rejerůw:",
-       "prefs-help-recentchangescount": "Ze listům ńydawnych pomjyńan, gyszichta zajt a rejer.",
-       "savedprefs": "Twoje sztalowańo we preferyncyjach zostoły naszkryflane.",
+       "prefs-help-recentchangescount": "Maksymalnŏ wielość: 1000",
+       "savedprefs": "Twoje sztelōnki były spamiyntane.",
        "timezonelegend": "Czasowo sztrefa",
        "localtime": "Lokalny czas:",
        "timezoneuseserverdefault": "Użyj domyślnygo czasu serwera ($1)",
        "prefs-searchoptions": "Sznupańe",
        "prefs-namespaces": "Raumy mjan",
        "default": "důmyślńy",
-       "prefs-files": "Pliki",
+       "prefs-files": "Zbiory",
        "youremail": "E-mail:",
        "username": "{{GENDER:$1|Mjano używocza}}:",
        "prefs-memberingroups": "Należy do {{PLURAL:$1|grupy|grup:}}",
        "right-bigdelete": "Wyćep zajty s dugům historyjům půmjyńań",
        "right-deleterevision": "Wyćepywańy a wćepywańy nazod wskazanych sprowjyń zajtůw",
        "right-deletedhistory": "Pokazuj historyjo usuńyntych sprowjyń, bez tekstu uopisu",
-       "right-browsearchive": "Sznupej za wyćepanymi zajtůma",
+       "right-browsearchive": "Szukej we skasowanych strōnach",
        "right-undelete": "Prziwrŏcanie skasowanych strōn",
        "right-suppressrevision": "Přyglůndańy i uodtwařańy sprowjyń schrůńůnych před admińistratorami",
        "right-suppressionlog": "Pokoż prywatne lůgi",
        "right-userrights-interwiki": "Edytuj uprawniynia używŏczōw na inkszych wiki",
        "right-siteadmin": "Zawjerańy i uodmykańy bazy danych",
        "newuserlogpage": "Ksiōnżka nowych używŏczōw",
-       "newuserlogpagetext": "To je rejer uostatńo utworzůnych kůnt użytkowńikůw",
+       "newuserlogpagetext": "To je regest tworzōnych używŏczōw.",
        "rightslog": "Regest uprawniyń używŏczōw",
-       "rightslogtext": "Rejer půmjyńań uprawńyń užytkowńikůw.",
+       "rightslogtext": "To je regest zmian uprawniyń używŏczōw.",
        "action-read": "přeglůndańo tyj zajty",
        "action-edit": "edycyje tyj strōny",
        "action-createpage": "tworzyńo zajtůw",
        "upload": "Zaladuj zbiōr",
        "uploadbtn": "Prziślij zbiōr",
        "reuploaddesc": "Nazod do formulařa uod wćepywańo.",
-       "uploadnologin": "Ńy jest žeś zalogůwany",
+       "uploadnologin": "Niy je żeś wlogowany(ŏ)",
        "uploadnologintext": "Muśyš śe [[Special:UserLogin|zalůgować]] ńim wćepńeš pliki.",
        "upload_directory_missing": "Katalog lo wćepywanych plikůw ($1) ńy istńeje a serwer WWW ńy poradźi go utwořić.",
        "upload_directory_read_only": "Serwer ńy može škryflać do katalůgu ($1) kery je přeznačůny na wćepywane pliki.",
        "filedelete-reason-otherlist": "Inkszy powůd",
        "filedelete-reason-dropdown": "* Nojczynstsze powody wyćepańa\n** Naruszyńy praw autorskych\n** Kopja plika kery już sam jest",
        "filedelete-edit-reasonlist": "Sprowjańe powodůw wyćepańo zajty",
-       "mimesearch": "Sznupej MIME",
+       "mimesearch": "Szukanie podle typu MIME",
        "mimesearch-summary": "Ta zajta ůmožliwjo šnupańe za plikůma wedle jeich typu MIME. Užyće: typtreśći/podtyp, np. <code>image/jpeg</code>.",
        "mimetype": "Typ MIME:",
        "download": "pobier",
        "unwatchedpages": "Zajty na kere ńy je dowany pozůr",
        "listredirects": "Lista przekerowań",
+       "listduplicatedfiles": "Lista zbiorōw ze tuplikatami",
        "unusedtemplates": "Niyużywane mustry",
        "unusedtemplatestext": "Půńižej znojdowo śe lista wšyjstkich zajtůw s přestřyńi mjan {{ns:template}}, kere ńy sům užywane bez inkše zajty. Sprowdź inkše adresowańa ku šablůnům, ńim wyćepńeš ta zajta.",
        "unusedtemplateswlh": "ku adresatu",
        "statistics-articles": "Zajty",
        "statistics-pages": "Zajty",
        "statistics-pages-desc": "Wszyjstke zajty na wiki, wroz ze zajtami godki, przekerowańami a t.p.",
-       "statistics-files": "Wćepane pliki",
+       "statistics-files": "Zaladowane zbiory",
        "statistics-edits": "Sprowjyńa wykůnane uod powstańo {{grammar:D.lp|{{SITENAME}}}}",
        "statistics-edits-average": "Strzedńo liczba sprowjyń na zajta",
        "statistics-users": "Zarejerowanych użytkowńikůw",
        "wantedpages": "Potrzebne strōny",
        "wantedfiles": "Potrzebne zbiory",
        "wantedtemplates": "Potrzebne mustry",
-       "mostlinked": "Nojczyńśćij adresowane",
-       "mostlinkedcategories": "Kategoryje we kerych je nojwjyncyj artikli",
+       "mostlinked": "Nojczyńścij linkowane",
+       "mostlinkedcategories": "Nojwiyncyj używane kategoryje",
        "mostlinkedtemplates": "Nojczyńśćij adresowane mustry",
-       "mostcategories": "Zajty kere majům nojwiyncyj kategoryjůw",
-       "mostimages": "Nojczyńśćij adresowane pliki",
-       "mostrevisions": "Nojczyńśćij sprowjane artikle",
+       "mostcategories": "Strōny, co majōm nojwiyncyj kategoryji",
+       "mostimages": "Nojczyńścij używane zbiory",
+       "mostinterwikis": "Strōny, co majōm nojwiyncyj linkōw interwiki",
+       "mostrevisions": "Nojwiyncyj edytowane strōny",
        "prefixindex": "Wszyjske strōny ze prefiksym",
        "shortpages": "Nojkrōtsze strōny",
        "longpages": "Duge strōny",
        "protectedpages-cascade": "Yno zajty zabezpjeczůne rekursywńy",
        "protectedpagesempty": "Żodno zajta ńy je terozki zawarto ze podanymi parametrami.",
        "protectedtitles": "Zastawiōne tytuły",
-       "protectedtitlesempty": "Do tych štalowań utwořyńy artikla uo dowolnym mjańy ńy je zawarte",
+       "protectedtitlesempty": "Żŏdne strōny niy sōm terŏz zawarte ze tymi parametrami.",
        "listusers": "Lista używŏczōw",
        "listusers-editsonly": "Pokoż yno użytkowńikůw kere majům sprowjyńa",
        "usereditcount": "$1 {{PLURAL:$1|sprowjyńe|sprowjyńa|sprowjyń}}",
        "specialloguserlabel": "Fto:",
        "speciallogtitlelabel": "Cyl (nazwa abo {{ns:user}}:miano ôd używŏcza):",
        "log": "Regest ôperacyji",
-       "all-logs-page": "Wszyjske Ã³peracyje",
+       "all-logs-page": "Wszyjske Ã´peracyje",
        "alllogstext": "Spōlne pokŏzanie wszyjskich dostympnych regestōw {{SITENAME}}.\nMożesz uakuratnić widok bez ôbranie zorty regestu, miana ôd używŏcza, abo tykanyj strōny (dŏwŏ pozōr na małe i sroge litery).",
        "logempty": "Niy ma we regeście zgodliwych elymyntōw.",
        "log-title-wildcard": "Szukej tytułōw, co sie zaczynajōm ôd tego tekstu",
        "categories": "Kategoryje",
        "categoriespagetext": "Zajta przedstowjo lista katygoryji s zajtůma a plikůma.\n[[Special:UnusedCategories|Ńyużywane kategoryj]] ńy zostoły tukej pokozane.\nKukńij tyż [[Special:WantedCategories|ńyistńyjůnce kategoryje]].",
        "categoriesfrom": "Pokož kategoryje začynajůnc uod:",
-       "deletedcontributions": "Wyćepane sprowjyńa użytkowńika",
-       "deletedcontributions-title": "Wyćepane sprowjyńa użytkowńika",
+       "deletedcontributions": "Skasowany wkłŏd ôd używŏcza",
+       "deletedcontributions-title": "Skasowany wkłŏd ôd używŏcza",
        "sp-deletedcontributions-contribs": "wkłŏd",
-       "linksearch": "Necowe uodwołańa",
+       "linksearch": "Szukanie zewnyntrznych linkōw",
        "linksearch-pat": "Wzorzec sznupańo",
        "linksearch-ns": "Przestrzyń mjan",
        "linksearch-ok": "Šnupej",
        "linksearch-text": "Idźe użyć symbola wjeloznacznygo „*”. Lů bajszpila „*.wikipedia.org” spowoduje sznupańy za wszyjstkimi linkůma kere prowadzům ku důmyńy „wikipedia.org” a jeij poddůmyn.<br />\nUobsůgiwane protokoły: $1",
        "linksearch-line": "$1 link na zajće $2",
        "linksearch-error": "Symbola wjeloznacznygo idźe użyć yno na anfangu mjana hosta.",
-       "listusersfrom": "Pokaž užytkowńikůw začynojůnc uod:",
+       "listusersfrom": "Pokŏż używŏczōw ôd:",
        "listusers-submit": "Uobejrzij",
        "listusers-noresult": "Ńy znejdźůno žodnygo užytkowńika.",
        "activeusers": "Lista aktywnych używŏczōw",
        "emailsend": "Wyślij",
        "emailccme": "Wyślij mi kopja moiy wjadomości.",
        "emailccsubject": "Kopja Twojej wjadůmośći do $1: $2",
-       "emailsent": "Wjadůmość zostoua wysuano",
-       "emailsenttext": "Twoja wjadůmość zostoua wysuano.",
+       "emailsent": "E-mail wysłany",
+       "emailsenttext": "Twoja wiadōmość e-mail je wysłanŏ.",
        "emailuserfooter": "Wjadůmość e-brif zostoła wysłano s {{GRAMMAR:D.lp|{{SITENAME}}}} ku $2 bez $1 s użyćym „Wyślij e-brif ku tym użytkowńikowi”.",
        "usermessage-editor": "Nadŏwca systymowych kōmunikatōw",
        "watchlist": "Ôbserwowane",
        "watchlistfor2": "{{GENDER:$1|Używŏcza|Używŏczki}} $1 $2",
        "nowatchlist": "Ńy ma žodnych pozycyji na liśće zajtůw, na kere dowoš pozůr.",
        "watchlistanontext": "$1 coby uobejřeć abo sprowjać elymynty listy zajtůw, na kere dowoš pozůr",
-       "watchnologin": "Ńy jest žeś zalůgowany",
+       "watchnologin": "Niy je żeś wlogowany(ŏ)",
        "addedwatchtext": "Zajta \"[[:$1]]\" zostoua dodano do Twojij [[Special:Watchlist|listy artiklůw, na kere dowoš pozůr]].\nNa tyi liśće bydźeš mjou rejer přišuych sprowjyń tyi zajty i jeji zajty godki, a mjano zajty bydźeš mjou škryflane '''tustym''' na [[Special:RecentChanges|liśće půmjyńanych na ůostatku]], cobyś mjou wygoda w jei pomjyńańa filować.",
        "removedwatchtext": "Artikel \"[[:$1]]\" zostou wyćepńjynty s [[Special:Watchlist|Twojij pozorlisty]].",
        "watch": "Ôbserwuj",
        "unwatch": "Niy ôbserwuj",
        "unwatchthispage": "Přestoń dować pozůr",
        "notanarticle": "To ńy je artikel",
-       "notvisiblerev": "Wersyja zostoua wyćepano",
+       "notvisiblerev": "Ôstatniŏ wersyjŏ ôd inkszego używŏcza była skasowanŏ",
        "watchlist-details": "Na Twojij liście ôbserwowanych {{PLURAL:$1|je $1 strōna|sōm $1 strōny|je $1 strōn}} (plus strōny dyskusyje).",
        "wlheader-enotif": "Wysůuańy powjadůmjyń na adres e-brif je zouůnčůne",
        "wlheader-showupdated": "Zajty, co były zmiyniane ôd twojij ôstatnij nŏwiydzki na nich ôstały ukŏzane <strong>na rubo</strong>.",
        "confirmdeletetext": "Zarŏz wyciepniesz artikel i cołkõ ôd niygo historyjõ. Przitupluj, iże na isto chcesz to zrobić, miarkujesz kōnsekwyncyje, i co robisz to podle [[{{MediaWiki:Policy-url}}|prawideł]].",
        "actioncomplete": "Fertig",
        "actionfailed": "Ńy udało śe.",
-       "deletedtext": "Wyćepano \"$1\". Rejer uostatnio zrobiůnych wyćepań možeš uobejžyć tukej: $2.",
+       "deletedtext": "Strōna „$1” była skasowanŏ.\nWejzdrzij na $2 po regest ôstatnich skasowań.",
        "dellogpage": "Regest kasowań",
        "dellogpagetext": "To je lista uostatńo wykůnanych wyćepań.",
-       "deletionlog": "rejer wyćepań",
+       "deletionlog": "regest skasowań",
        "reverted": "Prziwrōcōnŏ poprzedniõ wersyjõ",
        "deletecomment": "Čymu:",
        "deleteotherreason": "Inkšy powůd:",
        "rollbacklink": "cŏfej",
        "rollbacklinkcount": "cŏfnij $1 {{PLURAL:$1|edycyjõ|edycyje|edycyji}}",
        "rollbackfailed": "Niy szło wycŏfać zmiany",
-       "cantrollback": "Ńy idże cofnůńć pomjyńyńo, sam je ino jedna wersyja tyi zajty.",
+       "cantrollback": "Niy idzie cŏfnōńć edycyje;\nôstatni edytōr to je jedyny autōr tyj strōny.",
        "alreadyrolled": "Ńy idźe lů zajty [[:$1|$1]] cofnůńć uostatńygo pomjyńeńa, kere wykonoł [[User:$2|$2]] ([[User talk:$2|godka]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]).\nKto inkszy zdůnżůł już to zrobić abo wprowadźił własne poprowki do treśći zajty.\n\nAutorym ostatńygo pomjyńyńo je terozki [[User:$3|$3]] ([[User talk:$3|godka]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Sprowjyńe uopisano: <em>$1</em>.",
        "revertpage": "Wycofano sprowjyńe użytkowńika [[Special:Contributions/$2|$2]] ([[User talk:$2|godka]]). Autor prziwrůcůnej wersyji to [[User:$1|$1]].",
        "modifiedarticleprotection": "zmiyniōł(yła) poziōm zawarciŏ „[[$1]]”",
        "unprotectedarticle": "uodymknyu [[$1]]",
        "movedarticleprotection": "przekludzůno sztalowańa zabezpjeczyńo s „[[$2]]” ku „[[$1]]”",
-       "protect-title": "Pomjyńeńe poźomu zawarćo „$1”",
+       "protect-title": "Zmiana poziōmu zawarciŏ „$1”",
        "prot_1movedto2": "[[$1]] přećepano do [[$2]]",
        "protect-legend": "Potwjyrdź zawarće",
        "protectcomment": "Čymu:",
-       "protectexpiry": "Wygaso:",
+       "protectexpiry": "Wygasŏ:",
        "protect_expiry_invalid": "Čas wygaśńjyńćo je zuy.",
        "protect_expiry_old": "Čas wygaśńjyńćo je w downiej ńiž terozki.",
-       "protect-text": "Sam tukej možyš uobejžeć i pomjyńyć poźům zawarcia zajty '''$1'''.",
+       "protect-text": "Sam możesz ôbejzdrzeć i zmiynić poziōmy zawarciŏ strōny <strong>$1</strong>.",
        "protect-locked-blocked": "Ńy možeš půmjyńać poźůmůw zawarćo kej žeś sům je zawarty uod sprowjyń. Terozki štalowańa dla zajty '''$1''' to:",
        "protect-locked-dblock": "Ńy idźe půmjyńić poźůmu zawarća s kuli tygo co baza danych tyž je zawarto. Uobecne štalowańa dla zajty '''$1''' to:",
        "protect-locked-access": "Ńy moš uprowńyń coby pomjyńyć poziům zawarcia zajty. Uobecne ustawjyńo dlo zajty '''$1''' to:",
        "protect-summary-cascade": "dźedźičyńy",
        "protect-expiring": "wygaso $1 (UTC)",
        "protect-expiry-indefinite": "na zowdy",
-       "protect-cascade": "Dźedźyčyńe zawarćo - zawřij wšyskie zajty kere sům na tyi zajće.",
+       "protect-cascade": "Zawrzij strōny, co sōm wrażōne do tyj strōny (erbowanie zawarciŏ)",
        "protect-cantedit": "Ńy možeš pomjyńyć poziůmu zawarća tyi zajty, po takiymu, co uona je dlo Ćebje zawarto uod pomjyńańa.",
        "protect-othertime": "Inkszy uokres:",
        "protect-othertime-op": "inkszy uokres",
        "protect-otherreason": "Inkszy/dodatkowy powůd:",
        "protect-otherreason-op": "inkszy/dodatkowy powůd",
        "protect-dropdown": "*Nojczynstsze powody zawarćo uod sprowjyń\n** Czynste wandalizmy\n** Czynste spamowańy\n** Wojna edycyjno\n** Wygupy",
-       "protect-edit-reasonlist": "Sprowjej powody zawarćo uod sprowjyń",
+       "protect-edit-reasonlist": "Edytuj powody zawarciŏ",
        "protect-expiry-options": "2 godźiny:2 hours,1 dźyń:1 day,3 dńi:3 days,1 tydźyń:1 week,2 tygodńy:2 weeks,1 mjeśůnc:1 month,3 mjeśůnce:3 months,6 mjeśency:6 months,1 rok:1 year,ńyskůńčůny:infińite",
        "restriction-type": "Pozwolyńy:",
-       "restriction-level": "Poźům:",
+       "restriction-level": "Poziōm:",
        "minimum-size": "Minimalnŏ srogość",
        "maximum-size": "Maksymalnŏ srogość:",
        "pagesize": "(bajtōw)",
        "undeleteinvert": "Zaznocz na uopy",
        "undeletecomment": "Powůd wćepańo nazod:",
        "cannotundelete": "Wćepańy nazod ńy powjodo śe.\nKto inkšy můgu wćepać nazod zajta pjyrwšy.",
-       "undeletedpage": "'''Wćepano nazod zajta $1.'''\n\nUobejřij [[Special:Log/delete|rejer wyćepań]], kejbyś chćou přeglůndnůnć uostatnie uoperacyje wyćepywańo i wćepywańo nazod zajtůw.",
-       "undelete-header": "Uobejřij [[Special:Log/delete|rejer wyćepań]] coby sprawdźić uostatńo wyćepane zajty.",
+       "undeletedpage": "<strong>Strōna „$1” była prziwrōcōnŏ</strong>\n\nWejzdrzij do [[Special:Log/delete|regestu skasowań]] po lista ôstatnich skasowań i prziwrōcyń.",
+       "undelete-header": "Wejzdrzij na [[Special:Log/delete|regest skasowań]] po ôstatnio skasowane strōny.",
        "undelete-search-box": "Šnupej za wyćepńjyntymi zajtami",
        "undelete-search-prefix": "Strōny, co sie zaczynajōm ôd:",
        "undelete-search-submit": "Šnupej",
        "block-log-flags-noemail": "e-mail zablokowany",
        "block-log-flags-nousertalk": "ńy może sprowjać włosnyj zajty godki",
        "block-log-flags-angry-autoblock": "rozszerzůne automatyczne zawjyrańe załůnczůne",
-       "range_block_disabled": "Možliwość zawjerańo zakresu adresůw IP zostoua wůuůnčůno.",
+       "range_block_disabled": "Blokowanie zŏkresu adres IP je zakŏzane.",
        "ipb_expiry_invalid": "Felerny čas wygaśńjyńćo zawarća.",
        "ipb_expiry_temp": "Schrůńůne mjano użytkowńika noleży zawrzić trwale.",
        "ipb_already_blocked": "\"$1\" je już zawarty uod sprowjyń",
        "lockbtn": "Zawřij baza danych",
        "unlockbtn": "Uodymkńij baza danych",
        "locknoconfirm": "Ńy zaznačůužeś potwjerdzyńo.",
-       "lockdbsuccesssub": "Baza danych zostoua půmyślńy zawarto",
-       "unlockdbsuccesssub": "Baza danych zostoua půmyślńy uodymkńynto",
-       "lockdbsuccesstext": "Baza danych zostoua zawarto.<br />\nPamjyntej coby [[Special:UnlockDB|jům uodymknůńć]] po zakůńčyńu dźouań admińistracyjnych.",
-       "unlockdbsuccesstext": "Baza danych zostoua uodymkńynto.",
+       "lockdbsuccesssub": "Zablokowanie bazy danych sie podarziło",
+       "unlockdbsuccesssub": "Blokada bazy danych symniyntŏ",
+       "lockdbsuccesstext": "Baza danych je zablokowanŏ.<br />\nPamiyntej, żeby [[Special:UnlockDB|jōm ôtworzić]] jak robota bydzie skōńczōnŏ.",
+       "unlockdbsuccesstext": "Baza danych je ôdblokowanŏ.",
        "lockfilenotwritable": "Ńy idźe naškreflać plika zawarća bazy danych.\nZawjerańy i uodmykańy bazy danych wymogo coby plik můgu być naškreflany bez web serwer.",
        "databasenotlocked": "Baza danych ńy je zawarto.",
        "move-page": "Przećep $1",
        "movepage-moved": "'''\"$1\" przećiśńjynto ku \"$2\"'''",
        "articleexists": "Artikel ze takym mjanym już je, abo mjano je złe.\nWybjer inksze mjano.",
        "cantmove-titleprotected": "Ńy możesz przećepnůńć zajty, beztuż co jeij nowe mjano je ńydozwolůne skuli zabezpjeczyńo przed utworzyńym",
-       "movetalk": "Przećiś godke, jak możno.",
+       "movetalk": "Przeniyś zwiōnzanõ ze strōnōm dyskusyjõ",
        "move-subpages": "Přećepńij podzajty",
        "move-talk-subpages": "Jeli je to możliwe przekludź wszyjstke zajty godki podzajtůw",
        "movepage-page-exists": "Zajta $1 już istńeje a ńy idźe jeij autůmatyczńy nadszkryflać.",
        "export-templates": "Douůnč šablůny",
        "allmessages": "Komunikaty",
        "allmessagesname": "Mjano",
-       "allmessagesdefault": "Tekst důmyślny",
+       "allmessagesdefault": "Wychodny tekst wiadōmości",
        "allmessagescurrent": "Tekst uobecny",
        "allmessagestext": "Uoto lista wšyjstkych kůmůńikatůw systymowych dostympnych w přestřyńi mjan MedjaWiki.\nUodwjydź [https://www.mediawiki.org/wiki/Special:MyLanguage/Localisation Tuůmačyńy MediaWiki] a tyž [https://translatewiki.net translatewiki.net] kejbyś chćou učestńičyć w tuůmačyńu uoprůgramowańo MediaWiki.",
        "allmessages-not-supported-database": "Ta zajta ńy može być užyta, bez tůž co zmjynna '''$wgUseDatabaseMessages''' je wůuůnčůno.",
        "import-token-mismatch": "Straćiły śe dane ze sesyje. Prosza spróbować zaś.",
        "import-invalid-interwiki": "Ńy idźe importować s podanyj wiki.",
        "importlogpage": "Regest importōw",
-       "importlogpagetext": "Rejer přeprowadzůnych importůw zajtůw s inkšych serwisůw wiki.",
+       "importlogpagetext": "Regest importōw strōn społym ze jejich historyjami ze inkszych wiki.",
        "import-logentry-upload-detail": "$1 {{PLURAL:$1|wersyja|wersyje|wersyji}}",
        "import-logentry-interwiki-detail": "$1 {{PLURAL:$1|wersyja|wersyje|wersyji}} ze $2",
        "tooltip-pt-userpage": "{{GENDER:|Moja}} strōna",
        "show-big-image-preview": "Srogość tego podglōndu: $1.",
        "show-big-image-other": "{{PLURAL:$2|Inkszŏ rozdzielczość|Inksze rozdzielczości}}: $1.",
        "show-big-image-size": "$1 x $2 pikselōw",
-       "newimages": "Galerjo nowych uobrozkůw",
+       "newimages": "Galeryjŏ nowych ôbrŏzkōw",
        "imagelisttext": "Půnižyj na {{PLURAL:$1||posortowanyj $2}} liśće {{PLURAL:$1|znojdowo|znojdujům|znojdowo}} śe '''$1''' {{PLURAL:$1|plik|pliki|plikůw}}.",
        "newimages-summary": "Na tyj ekstra zajće prezyntowane sům uostatńo wćepńynte pliki.",
        "newimages-legend": "Filtruj",
        "confirmemail_text": "Projekt {{SITENAME}} wymago weryfikacyji adresa e-brif před užyćym fůnkcyji kořistajůncych s počty.\nWćiś knefel půńižy coby wysúać na swůj adres list s linkym do zajty WWW.\nList bydźe zawjeroú link do zajty, w kerym zakodowany bydźe idyntyfikator.\nUodymkńij tyn link we přyglůndarce, čym potwjerdźiš, co ježeś užytkowńikym tygo adresa e-brif.",
        "confirmemail_pending": "Kod potwierdzyniŏ bōł prawie do Ciebie wysłany. Jak Twoje kōnto było niydŏwno zaregistrowane, to poczekej pŏrã minut na jego dotarcie, podwiela wyślesz prośbã ô nowy.",
        "confirmemail_send": "Wyślij kod potwjerdzyńo",
-       "confirmemail_sent": "Wjadůmość e-brif s kodym uwjeřitelńajůncym zostoua wysuano.",
+       "confirmemail_sent": "E-mail ze potwiyrdzyniym wysłany.",
        "confirmemail_oncreate": "Link s kodym potwjerdzyńo zostou wysuany na Twůj adres e-brif.\nKod tyn ńy je wymagany coby śe sam lůgować, ale bydźeš muśou go aktywować uodmykajůnc uotřimany link we přyglůndarce ńim zouůnčyš ńykere uopcyje e-brif na wiki.",
        "confirmemail_sendfailed": "{{SITENAME}} ńy poradźiła wysłać potwjerdzajůncyj wjadůmośći e-brif.\nSprowdź aże we adreśe ńy ma felernyj buchsztaby.\n\nSystym pocztowy zwrůćił kůmůńikat: $1",
        "confirmemail_invalid": "Felerny kod potwjerdzyńo.\nKod može być předawńůny",
        "watchlistedit-normal-legend": "Wyćep zajty s listy artikli na kere dowoš pozůr",
        "watchlistedit-normal-explain": "Půńiżyj mosz lista artikli na kere dowosz pozůr.\nCoby wyćepać z ńij jako zajta, zaznocz pole przi ńij i naćiś knefel „{{int:Watchlistedit-normal-submit}}”.\nMożesz tyż skorzistać ze [[Special:EditWatchlist/raw|tekstowygo sprowjorza listy artikli na kere dowosz pozůr]].",
        "watchlistedit-normal-submit": "Wyćep s listy",
-       "watchlistedit-normal-done": "Z Twoi listy artikli na kere dowoš pozůr {{PLURAL:$1|zostoua wyćepano 1 zajta|zostouy wyćepane $1 zajty|zostouo wyćepanych $1 zajtůw}}:",
+       "watchlistedit-normal-done": "{{PLURAL:$1|Była skasowanŏ jedna strōna|Były skasowane $1 strōny|Było skasowanych $1 strōn}} ze twojij listy ôbserwowanych:",
        "watchlistedit-raw-title": "Tekstowy edytor listy artikli na kere dowosz pozůr",
        "watchlistedit-raw-legend": "Tekstowy edytor listy artikli na kere dowoš pozůr",
        "watchlistedit-raw-explain": "Půńižy moš lista artikli na kere dowoš pozůr. W koždej lińii znojdowo śe titel jydnygo artikla. Lista možeš sprowjać dodajůnc nowe zajty i wyćepujůnc te kere na ńij sům. Jak skůńčyš, naćiś knefel „Uaktualńij lista zajtůw na kere dowům pozůr”.\nMožeš tyž [[Special:EditWatchlist|užyć standardowygo edytora]].",
        "watchlistedit-raw-titles": "Title:",
        "watchlistedit-raw-submit": "Uaktualńij lista",
-       "watchlistedit-raw-done": "Lista zajtůw na kere dowoš pozůr zostoua uaktualńůna",
+       "watchlistedit-raw-done": "Lista twojich ôbserwowanych była zaktualizowanŏ.",
        "watchlistedit-raw-added": "Dodano {{PLURAL:$1|1 pozycyja|$1 pozycyje|$1 pozycyji}} do listy artikli na kere dowoš pozůr:",
        "watchlistedit-raw-removed": "Wyćepano {{PLURAL:$1|1 pozycyja|$1 pozycyje|$1 pozycyji}} z listy zajtůw na kere dowoš pozůr:",
        "watchlisttools-clear": "Wysnŏż ôbserwowane",
        "redirect-page": "Idyntyfikatōr strōny",
        "redirect-revision": "Wersyjŏ strōny",
        "redirect-file": "Miano zbioru",
-       "fileduplicatesearch": "Šnupej za duplikatym plika",
+       "fileduplicatesearch": "Szukej tuplikatōw zbioru",
        "fileduplicatesearch-summary": "Šnupej za duplikatůma plika na podstawje wartośći fůnkcyji skrůtu.",
        "fileduplicatesearch-filename": "Mjano pliku:",
        "fileduplicatesearch-submit": "Šnupej",
        "specialpages": "Ekstra strōny",
        "specialpages-note-restricted": "* Ekstra zajty uogůlńy dostympne.\n* <strong class=\"mw-specialpagerestricted\">Ekstra zajty do kerych dostymp je uograńiczůny.</strong>",
        "specialpages-group-maintenance": "Reporty kōnserwacyjne",
-       "specialpages-group-other": "Inkše ekstra zajty",
+       "specialpages-group-other": "Inksze ekstra strōny",
        "specialpages-group-login": "Logowanie / registracyjŏ",
-       "specialpages-group-changes": "Pomjyńane na uostatku a rejery",
-       "specialpages-group-media": "Pliki",
+       "specialpages-group-changes": "Ôstatnie zmiany i regesty",
+       "specialpages-group-media": "Zbiory",
        "specialpages-group-users": "Używŏcze i uprawniynia",
-       "specialpages-group-highuse": "Zajty čynsto užywane",
+       "specialpages-group-highuse": "Czynsto używane strōny",
        "specialpages-group-pages": "Listy strōn",
-       "specialpages-group-pagetools": "Nořyńdźa zajtůw",
-       "specialpages-group-wiki": "Informacyje a werkcojgi wiki",
-       "specialpages-group-redirects": "Ekstra zajty, kere kerujům",
+       "specialpages-group-pagetools": "Norzyńdzia strōn",
+       "specialpages-group-wiki": "Norzyńdzia i dane",
+       "specialpages-group-redirects": "Ekstra zajty przekerowaniŏ",
        "specialpages-group-spam": "Nořyńdźa do wyćepywanio spamu",
        "blankpage": "Pusto zajta",
        "intentionallyblankpage": "Ta zajta nauůmyślńy uostoua śe pusto",
        "searchsuggest-search": "Szukej we {{SITENAME}}",
        "duration-days": "$1 {{PLURAL:$1|dziyń|dni}}",
        "expand_templates_ok": "OK",
+       "mediastatistics": "Statystyki mediōw",
        "randomrootpage": "Losowŏ strōna (bez podstrōn)",
        "changecredentials": "Zmiyń poświadczynia",
-       "changecredentials-submit": "Zmiyń poświadczynia"
+       "changecredentials-submit": "Zmiyń poświadczynia",
+       "removecredentials": "Kasowanie poświadczyń"
 }
index e64f8fa..f9c80aa 100644 (file)
        "protectedpagetext": "ఈ పేజీలో మార్పులు వగైరాలు చెయ్యకుండా ఉండేందుకు గాను, సంరక్షించబడింది.",
        "viewsourcetext": "మీరీ పేజీ సోర్సును చూడవచ్చు, కాపీ చేసుకోవచ్చు.",
        "viewyourtext": "ఈ పేజీలో <strong>మీరు చేసిన మార్పుల</strong> మూలాన్ని చూడవచ్చు, కాపీ చేసుకోవచ్చు.",
-       "protectedinterface": "à°\88 à°ªà±\87à°\9cà±\80, à°\88 à°µà°¿à°\95à±\80 à°¯à±\8aà°\95à±\8dà°\95 à°¸à°¾à°«à±\8dà°\9fà±\81à°µà±\87à°°à±\81 à°\87à°\82à°\9fà°°à±\81à°«à±\87à°¸à±\81à°\95à±\81 à°\9aà±\86à°\82దిన à°\9fà±\86à°\95à±\8dà°¸à±\8dà°\9fà±\81à°¨à±\81 à°\85à°\82దిసà±\8dà°¤à±\81à°\82ది. à°¦à±\81à°¶à±\8dà°\9aà°°à±\8dయల à°¨à°¿à°µà°¾à°°à°£ à°\95à±\8bసమà±\88 à°¦à±\80à°¨à±\8dని à°¸à°\82à°°à°\95à±\8dà°·à°¿à°\82à°\9aà°¾à°\82. à°µà°¿à°\95à±\80లనà±\8dనిà°\9fà°¿à°²à±\8bà°¨à±\81 అనువాదాలను చేర్చాలన్నా, మార్చాలన్నా మీడియావికీ స్థానికీకరణ ప్రాజెక్టైన [https://translatewiki.net/ translatewiki.net] ను వాడండి.",
+       "protectedinterface": "à°\88 à°ªà±\87à°\9cà±\80, à°\88 à°µà°¿à°\95à±\80 à°¯à±\8aà°\95à±\8dà°\95 à°\87à°\82à°\9fà°°à±\81à°«à±\87à°¸à±\81à°\95à±\81 à°\9aà±\86à°\82దిన à°\9fà±\86à°\95à±\8dà°¸à±\8dà°\9fà±\81à°¨à±\81 à°\85à°\82దిసà±\8dà°¤à±\81à°\82ది. à°¦à±\81à°¶à±\8dà°\9aà°°à±\8dయలనà±\81 à°¨à°¿à°µà°¾à°°à°¿à°\82à°\9aà±\87à°\82à°¦à±\81à°\95à±\88 à°¦à±\80à°¨à±\8dని à°¸à°\82à°°à°\95à±\8dà°·à°¿à°\82à°\9aà°¾à°\82. à°µà°¿à°\95à±\80లనà±\8dనిà°\9fà°¿à°²à±\8b అనువాదాలను చేర్చాలన్నా, మార్చాలన్నా మీడియావికీ స్థానికీకరణ ప్రాజెక్టైన [https://translatewiki.net/ translatewiki.net] ను వాడండి.",
        "editinginterface": "<strong>హెచ్చరిక:</strong> సాఫ్టువేరుకు ఇంటరుఫేసు టెక్స్టును అందించేందుకు పనికొచ్చే పేజీని మీరు సరిదిద్దుతున్నారు.\nఈ పేజీలో చేసే మార్పుల వల్ల ఇతర వాడుకరులకు కనబడే ఇంటరుఫేసు ప్రభావితమౌతుంది.",
        "translateinterface": "అన్ని వికీలలో కనిపించేలా అనువాదాలు చేర్చాలన్నా, మార్చాలన్నా, దయచేసి [https://translatewiki.net/ translatewiki.net] ను వాడండి. ఇది మీడియావికీ స్థానికీకరణ ప్రాజెక్టు.",
        "cascadeprotected": "కింది {{PLURAL:$1|పేజీని|పేజీలను}} కాస్కేడింగు ఆప్షనుతో సంరక్షించబడింది. ప్రస్తుత పేజీ, ఈ పేజీల్లో ట్రాన్స్‌క్లూడు అయి ఉంది కాబట్టి, దిద్దుబాటు చేసే వీలు లేకుండా ఇది కూడా రక్షణలో ఉంది:\n$2",
index 4735c4c..821ce9d 100644 (file)
        "nocreate-loggedin": "Yeni sayfalar oluşturmaya yetkiniz yok.",
        "sectioneditnotsupported-title": "Bölüm değiştirmesi desteklenmiyor",
        "sectioneditnotsupported-text": "Bölüm değiştirmesi bu sayfada desteklenmiyor.",
+       "modeleditnotsupported-title": "Düzenleme desteklenmemektedir",
        "permissionserrors": "İzin hatası",
        "permissionserrorstext": "Aşağıdaki {{PLURAL:$1|sebep|sebepler}}den dolayı, bunu yapmaya yetkiniz yok:",
        "permissionserrorstext-withaction": "Aşağıdaki {{PLURAL:$1|neden|nedenler}}den dolayı $2 yetkiniz yok:",
        "content-model-css": "CSS",
        "content-json-empty-object": "Boş nesne",
        "content-json-empty-array": "Boş dizi",
+       "unsupported-content-model": "<strong>Uyarı:</strong> İçerik modeli $1 desteklenmemektedir",
+       "unsupported-content-diff": "İçerik modeli $1 için değişiklikler desteklenmemektedir.",
+       "unsupported-content-diff2": "İçerik modeli  $1 ve $2 arasındaki değişiklikler bu vikide desteklenmemektedir.",
        "deprecated-self-close-category": "Kendiliğinden geçersiz HTML etiketlerini kullanan sayfalar",
        "deprecated-self-close-category-desc": "Sayfa, <code>&lt;b/></code> veya <code>&lt;span/></code> gibi kendiliğinden geçersiz HTML etiketleri içeriyor. Bunların davranışları yakında HTML5 belirtimiyle tutarlı olacak şekilde değişecektir, bu nedenle wikitext'deki kullanımları, kullanımdan kaldırılır.",
        "duplicate-args-warning": "<strong>Uyarı:</strong>[[:$1]] [[:$2]] şablonunu \"$3\" parametresi için birden fazla değerle çağırıyor. Sadece sağlanan son değer kullanılacak.",
        "undo-norev": "Değişiklik geri alınamaz çünkü ya silinmiş ya da varolmamaktadır.",
        "undo-nochange": "Düzeltme zaten geri alınmış.",
        "undo-summary": "$1 değişikliği [[Special:Contributions/$2|$2]] ([[User talk:$2|mesaj]]) tarafından geri alındı.",
+       "undo-summary-anon": "[[Special:Contributions/$2|$2]] tarafından yapılan değişiklik $1'i geri al",
        "undo-summary-username-hidden": "Gizli bir kullanıcı tarafından $1 sürümü geri alınıyor",
        "cantcreateaccount-text": "Bu IP adresinden ('''$1''') kullanıcı hesabı oluşturulması [[User:$3|$3]] tarafından engellenmiştir.\n\n$3 tarafından verilen sebep ''$2''",
        "cantcreateaccount-range-text": "<strong>$1</strong> aralığındaki IP'ler için hesap oluşturma [[User:$3|$3]] tarafından engellendi, bu sizin IP adresinizi de (<strong>$4</strong>) içeriyor.\n\n$3 tarafından verilen gerekçe <em>$2</em>",
        "backend-fail-contenttype": "\"$1\" konumunda saklanan dosyanın içerik türü belirlenemiyor.",
        "backend-fail-batchsize": "Depolama arkaplan uygulamasına $1 dosya {{PLURAL:$1|işlemi|işlemi}} yığını verildi; sınır $2 {{PLURAL:$1|işlem|işlem}}.",
        "backend-fail-usable": "Yetersiz izinlerden ya da eksik dizin/konteynerlerden dolayı \"$1\" dosyası okunup yazılamıyor.",
+       "backend-fail-stat": "Dosya \"$1\" durumu okunamıyor.",
+       "backend-fail-hash": "Dosya \"$1\"e ait kriptografi belirlenemedi.",
        "filejournal-fail-dbconnect": "\"$1\" depolama arkaplan uygulaması için günlük veri tabanına erişilemiyor.",
        "filejournal-fail-dbquery": "\"$1\" depolama arkaplan uygulaması için günlük veri tabanı güncellenemiyor.",
        "lockmanager-notlocked": "\"$1\" kilidi açılamıyor; kilitli değil.",
index 16310eb..bda0a4f 100644 (file)
        "grouppage-suppress": "{{ns:project}}:Назирләр",
        "right-read": "Битләрне карау",
        "right-edit": "Битләрне үзгәртү",
-       "right-createpage": "биÑ\82лÓ\99Ñ\80 Ñ\8fÑ\81аÑ\83 (бÓ\99Ñ\85Ó\99Ñ\81 Ð±Ñ\83лмаганнаÑ\80Ñ\8bн)",
-       "right-createtalk": "бÓ\99Ñ\85Ó\99Ñ\81 Ð±Ð¸Ñ\82ен Ñ\8fÑ\81аÑ\83",
-       "right-createaccount": "яңа кулланучы хисап язмасын ясау",
+       "right-createpage": "Ð\91иÑ\82лÓ\99Ñ\80не Ñ\82өзү (бÓ\99Ñ\85Ó\99Ñ\81 Ð±Ð¸Ñ\82лÓ\99Ñ\80е Ð±Ñ\83лмаган)",
+       "right-createtalk": "Ð\91Ó\99Ñ\85Ó\99Ñ\81 Ð±Ð¸Ñ\82лÓ\99Ñ\80ен Ñ\82өзү",
+       "right-createaccount": "Яңа кулланучы хисап язмасын төзү",
        "right-minoredit": "\"кече төзәтмә\" тамгасын кую",
        "right-move": "Битләрне күчерү",
        "right-move-subpages": "Битләрне асбитләр белән бергә күчерү",
index 519a355..cc2e664 100644 (file)
@@ -97,7 +97,7 @@
        "tog-watchdefault": "Додавати змінені мною сторінки та файли до мого списку спостереження",
        "tog-watchmoves": "Додавати перейменовані мною сторінки та файли до мого списку спостереження",
        "tog-watchdeletion": "Додавати вилучені мною сторінки та файли до мого списку спостереження",
-       "tog-watchuploads": "Додавати до мого списку спостереження нові файли, завантажені мною",
+       "tog-watchuploads": "Додавати файли, завантажені мною до списку спостереження",
        "tog-watchrollback": "Додавати відкочені мною сторінки до мого списку спостереження",
        "tog-minordefault": "Позначати всі зміни як незначні за замовчуванням",
        "tog-previewontop": "Показувати попередній перегляд перед вікном редагування, а не після",
        "tog-useeditwarning": "Попереджати мене, якщо я залишаю сторінку редагування з незбереженими змінами",
        "tog-prefershttps": "Завжди використовувати безпечне з'єднання при вході в систему",
        "tog-showrollbackconfirmation": "Показати підтверджувальне вікно при натисканні на посилання відкоту",
+       "tog-requireemail": "Вимагає вказання електронної пошти для скидання пароля",
        "underline-always": "Завжди",
        "underline-never": "Ніколи",
        "underline-default": "Використовувати налаштування браузера",
        "category-empty": "''Ця категорія зараз порожня.''",
        "hidden-categories": "{{PLURAL:$1|1=Прихована категорія|Приховані категорії}}",
        "hidden-category-category": "Приховані категорії",
-       "category-subcat-count": "{{PLURAL:$2|Показано $1 {{PLURAL:$1|підкатегорію з|підкатегорії з|підкатегорій із}} $2.|1=Ця категорія має тільки таку підкатегорію.}}",
+       "category-subcat-count": "{{PLURAL:$2|1=Ця категорія має тільки таку підкатегорію.|Показано $1 {{PLURAL:$1|підкатегорію з|підкатегорії з|підкатегорій із}} $2.}}",
        "category-subcat-count-limited": "У цій категорії {{PLURAL:$1|$1 підкатегорія|$1 підкатегорії|$1 підкатегорій}}.",
        "category-article-count": "Показано $1 {{PLURAL:$1|сторінку|сторінки|сторінок}} цієї категорії (із $2).",
        "category-article-count-limited": "У цій категорії {{PLURAL:$1|$1 сторінка|$1 сторінки|$1 сторінок}}.",
        "changeemail-nochange": "Будь ласка, введіть адресу електронної пошти, відмінну від попередньої.",
        "resettokens": "Скидання токенів",
        "resettokens-text": "Ви можете скинути токени, що забезпечують доступ до певних особистих даних, пов'язаних тут із вашим обліковим записом.\nВам слід це зробити, якщо ви випадково поділились токенами з кимось, або якщо ваш обліковий запис було зламано.",
-       "resettokens-no-tokens": "Немає жетонів до скидання.",
+       "resettokens-no-tokens": "Немає токенів до скидання.",
        "resettokens-tokens": "Токени:",
        "resettokens-token-label": "$1 (поточне значення: $2)",
        "resettokens-watchlist-token": "Маркер стрічки новин (Atom/RSS) щодо [[Special:Watchlist|зміни на сторінці з вашого списку спостереження]]",
        "undo-norev": "Редагування не може бути скасоване, бо його не існує або було вилучено.",
        "undo-nochange": "Схоже, редагування вже було скасовано.",
        "undo-summary": "Скасування редагування № $1 користувача [[Special:Contribs/$2|$2]] ([[User talk:$2|обговорення]])",
+       "undo-summary-anon": "Скасування версії $1 від [[Special:Contributions/$2|$2]]",
        "undo-summary-username-hidden": "Скасувати версію $1, виконану прихованим користувачем",
        "cantcreateaccount-text": "Створення облікових записів із цієї IP-адреси ('''$1''') було заблоковане [[User:$3|користувачем $3]].\n\n$3 зазначив таку причину: ''$2''",
        "cantcreateaccount-range-text": "Створення облікового запису із IP-адрес у діапазоні  <strong>$1</strong>, який включає вашу IP-адресу (<strong>$4</strong>), було заблоковано користувачем [[User:$3|$3]].\n\nКористувач $3 вказав як причину <em>$2</em>",
        "prefs-help-email": "Адреса електронної пошти не є обов'язковою, але необхідна для скидання пароля, якщо Ви його забудете.",
        "prefs-help-email-others": "Також вона дозволить іншим користувачам зв'язатися з Вами через посилання на Вашій сторінці користувача чи на сторінці обговорення. При цьому Ваша електронна адреса залишиться нерозкритою.",
        "prefs-help-email-required": "Потрібно зазначити адресу електронної пошти.",
+       "prefs-help-requireemail": "Якщо вибране, то надішле електронного листа із скинутим паролем за умови, що в обліковому записі було вказано ім'я користувача та електронна пошта.",
        "prefs-info": "Основні відомості",
        "prefs-i18n": "Інтернаціоналізація",
        "prefs-signature": "Підпис",
        "alreadyrolled": "Неможливо відкинути останні редагування [[:$1]], зроблені [[User:$2|$2]] ([[User talk:$2|обговорення]]{{int:pipe-separator}}[[Special:Contributions/$2|{{int:contribslink}}]]), оскільки хтось інший уже змінив чи відкинув редагування цієї статті.\n\nОстанні редагування зроблено [[User:$3|$3]] ([[User talk:$3|обговорення]]{{int:pipe-separator}}[[Special:Contributions/$3|{{int:contribslink}}]]).",
        "editcomment": "Пояснення редагування було: «<em>$1</em>.».",
        "revertpage": "Відкинуто редагування [[Special:Contributions/$2|$2]] ([[User talk:$2|обговорення]]) до зробленого [[User:$1|$1]]",
+       "revertpage-anon": "Відкинуто правки [[Special:Contributions/$2|$2]] до останньої версії [[User:$1|$1]]",
        "revertpage-nouser": "Відкинуто редагування прихованого користувача до останньої версії, зробленої {{GENDER:$1|[[User:$1|$1]]}}",
        "rollback-success": "Відкинуті редагування {{GENDER:$3|користувача|користувачки}} $1; повернення до версії {{GENDER:$4|користувача|користувачки}} $2.",
        "sessionfailure-title": "Помилка сеансу",
        "ipblocklist-legend": "Пошук заблокованого користувача",
        "blocklist-userblocks": "Сховати блокування облікових записів",
        "blocklist-tempblocks": "Сховати тимчасові блокування",
+       "blocklist-indefblocks": "Сховати безстрокові блокування",
        "blocklist-addressblocks": "Приховати блокування окремих IP-адрес",
        "blocklist-type": "Тип:",
        "blocklist-type-opt-all": "Всі",
index d0d4c8a..edf53b2 100644 (file)
        "history": "ⴰⵎⵣⵔⴰⵢ ⵏ ⵜⴰⵙⵏⴰ",
        "history_short": "ⴰⵎⵣⵔⵓⵢ",
        "history_small": "ⴰⵎⵣⵔⵓⵢ",
-       "updatedmarker": "âµ\9cⵡⴰâµ\99âµ\99âµ\8fâ´¼âµ\8d âµ\9câµ\89â´³âµ\89âµ\94â´° âµ\8f âµ\93âµ\94ⵣⴰⴼ âµ\89âµ\8fâµ\93",
+       "updatedmarker": "âµ\9cⵡⴰâµ\99âµ\99âµ\8fâ´¼âµ\8d âµ\9câµ\89â´³âµ\89âµ\94â´° âµ\8f âµ\93âµ\94ⵣⴰⴼ âµ\8fâ´½:",
        "printableversion": "ⵜⵓⵏⵖⵉⵍⵜ ⵉⵜⵜⵡⴰⵙⵉⴳⴳⵣⵏ",
        "permalink": "ⴰⵙⵖⵏ ⴰⵎⵖⵍⴰⵍ",
        "print": "ⵙⵉⴳⴳⵣ",
        "accmailtitle": "ⵜⴰⴳⵓⵔⵉ ⵓⵣⵔⴰⵢ ⵜⴻⵜⵜⵡⴰⵣⵏ",
        "newarticle": "(ⴰⵎⴰⵢⵏⵓ)",
        "newarticletext": "ⵜⴹⴼⴰⵔⴷ ⵢⴰⵏ ⵓⵙⵖⵏ ⵖⵔ ⵢⴰⵜ ⵜⴰⵙⵏⴰ ⵏⵏⴰ ⵓⵔ ⵜⴰ ⵉⵍⵍⵉⵏ. \nⴰⴼⴰⴷ ⴰⴷ ⵜⵙⵏⵓⵍⴼⵓⴷ ⵜⴰⵙⵏⴰ, ⵙⵙⵏⵜⵉ ⵜⵉⵔⵔⴰ ⴳ ⵓⴼⵏⵉⵇ ⴳ ⵉⵣⴷⴷⴰⵔ (ⵥⵔ [$1 ⵜⴰⵙⵏⴰ ⵏ ⵜⵡⵉⵙⵉ] ⵉ ⵡⵓⴳⴳⴰⵔ ⵏ ⵉⵏⵖⵎⵉⵙⵏ). \nⵎⴽ ⵜⵍⵍⵉⴷ ⴷⴰ ⵙ ⵓⵣⴳⴰⵍ, ⴰⴽⵍ ⵖⴼ <strong>ⴰⵖⵓⵍ</strong> ⴳ ⵓⵙⴰⵔⴰ ⵏⵏⴽ.",
-       "anontalkpagetext": "----\n<em>ⵜⵍⵍⵉⴷ ⴳ ⵜⴰⵙⵏ ⵏ ⵓⵎⵙⴰⵡⴰⵍ ⵏ ⵢⴰⵏ ⵓⵏⵙⵙⵎⵔⵙ ⵡⴰⵔⵉⵙⵎ ⵏⵏⴰ ⵜⴰ ⵓⵔ ⵉⵙⴽⵉⵔⵏ ⴰⵎⵉⴹⴰⵏ ⵏⵖ ⵏⵏⴰ ⵜ ⵓⵔ ⵉⵙⵙⵎⵔⵉⵙⵏ</em>.\nⴰⵢⴰ ⴰ ⵖⴼ ⵉⴼⵓⴽⴽ ⴰⴷ ⵏⵙⵙⵎⵔⵙ ⵜⴰⵏⵙⴰ ⵏⵏⵙ IP ⴼⴰⴷ ⴰⴷ ⵜ ⵏⵙⵎⴰⴳⵉ.\nⵢⴰⵜ ⵜⴰⵏⵙⴰ IP ⵥⴹⴰⵔⵏ ⴰⴷ ⵜⵜ ⵙⵙⵓⵔⵏ ⵎⵏⵏⴰⵡ ⵏ ⵉⵏⵙⵙⵎⵔⵙⵏ.\nⵎⴽ ⵜⴳⵉⴷ ⵢⴰⵏ ⵓⵏⵙⵙⵎⵔⵙ ⵡⴰⵔⵉⵙⵎ ⴷ ⴽ ⵜⵖⴹⴼⴷ ⵎⴰⵙ ⴽ ⵡⴰⵜⵙⵏ ⴽⵔⴰ ⵏ ⵉⵅⴼⴰⵡⴰⵍⵏ ⵓⵔ ⵙⵉⴽ ⵉⵥⵍⵉⵏ, ⵜⵓⴼⵉⴷ ⴰⴷ  [[Special:CreateAccount|ⵙⴽⵔ ⵢⴰⵏ ⵓⵎⵉⴹⴰⵏ]] ⵏⵖ ⴷ [[Special:UserLogin|ⴽⵛⵎ]] ⴱⴰⵔ ⴰⴷ ⵜⴰⵏⴼⴷ ⵉ ⴽⵔⴰⵢⴳⴰⵜ ⴰⵎⵔⴽⵙ ⴷ ⵉⵎⴷⵔⴰⵡⵏ ⵢⴰⴹⵏ.",
+       "anontalkpagetext": "----\n<em>ⵜⵍⵍⵉⴷ ⴳ ⵜⴰⵙⵏ ⵏ ⵓⵎⵙⴰⵡⴰⵍ ⵏ ⵢⴰⵏ ⵓⵏⵙⵙⵎⵔⵙ ⵡⴰⵔⵉⵙⵎ ⵏⵏⴰ ⵜⴰ ⵓⵔ ⵉⵙⴽⵉⵔⵏ ⴰⵎⵉⴹⴰⵏ ⵏⵖ ⵏⵏⴰ ⵜ ⵓⵔ ⵉⵙⵙⵎⵔⵉⵙⵏ</em>.\nⴰⵢⴰ ⴰ ⵖⴼ ⵉⴼⵓⴽⴽ ⴰⴷ ⵏⵙⵙⵎⵔⵙ ⵜⴰⵏⵙⴰ ⵏⵏⵙ IP ⴼⴰⴷ ⴰⴷ ⵜ ⵏⵙⵎⴰⴳⵉ.\nⵢⴰⵜ ⵜⴰⵏⵙⴰ IP ⵥⴹⴰⵔⵏ ⴰⴷ ⵜⵜ ⵙⵙⵓⵔⵏ ⵎⵏⵏⴰⵡ ⵏ ⵉⵏⵙⵙⵎⵔⵙⵏ.\nⵎⴽ ⵜⴳⵉⴷ ⵢⴰⵏ ⵓⵏⵙⵙⵎⵔⵙ ⵡⴰⵔⵉⵙⵎ ⴷ ⴽ ⵜⵖⴹⴼⴷ ⵎⴰⵙ ⴽ ⵡⴰⵜⵙⵏ ⴽⵔⴰ ⵏ ⵉⵅⴼⴰⵡⴰⵍⵏ ⵓⵔ ⵙⵉⴽ ⵉⵥⵍⵉⵏ, ⵜⵓⴼⵉⴷ ⴰⴷ  [[Special:CreateAccount|ⵙⴽⵔ ⵢⴰⵏ ⵓⵎⵉⴹⴰⵏ]] ⵏⵖ ⴷ [[Special:UserLogin|ⴽⵛⵎ]] ⴱⴰⵔ ⴰⴷ ⵜⴰⵏⴼⴷ ⵉ ⴽⵔⴰⵢⴳⴰⵜ ⴰⵎⵔⴽⵙ ⴷ ⵉⵎⴷⵔⴰⵡⵏ ⵢⴰⴹⵏ.",
        "noarticletext": "ⵓⵔ ⵉⵍⵍⵉ ⴽⵔⴰ ⵏ ⵓⴹⵔⵉⵙ ⴳ ⵜⴰⵙⵏⴰ ⴰⴷ ⵖⵉⵍⴰ. \nⵜⵣⵎⵔⴷ ⴰⴷ [[Special:Search/{{PAGENAME}}|ⵜⵔⵣⵓⴷ ⵖⴼ ⵓⵣⵡⵍ ⵏⵏⵙ]] ⴳ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵢⴰⴹⵏ, <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ⵔⵣⵓ ⵖⴼ logs ⵖⵔⵙ ⵉⵇⵇⵏⴻⵏ],\nⵏⵖ [{{fullurl:{{FULLPAGENAME}}|action=edit}} ⵙⵏⵓⵍⴼⵓ ⵜⴰⵙⵏⴰ]</span>.",
        "noarticletext-nopermission": "ⴷⵖⵉ ⵓⵔ ⵉⵍⵍⵉ ⴰⵡⴷ ⴽⵔⴰ ⵏ ⵓⴹⵔⵉⵚ ⴳ ⵜⴰⵙⵏⴰ ⴰ.\nⵜⵣⵎⵔⴷ ⴰⴷ [[Special:Search/{{PAGENAME}}|ⵜⵔⵣⵓⴷ ⵖⴼ ⵓⵣⵡⵍ ⵏⵏⵙ]] ⴳ ⵜⴰⵙⵏⵉⵡⵉⵏ ⵢⴰⴹⵏⵉⵏ, ⵏⵖ <span class=\"plainlinks\">[{{fullurl:{{#Special:Log}}|page={{FULLPAGENAMEE}}}} ⵔⵣⵓ ⵖⴼ ⵉⵣⵎⵎⴻⵎⵏ ⵉⵣⴷⵉⵏ]</span>, ⵎⴰⵛⴰ ⵓⵔ ⴷⴰⵔⴽ ⵜⵓⵔⴰⴳⵜ ⴰⴷ ⵜⵙⵏⵓⵍⴼⵓⴷ ⵜⴰⵙⵏⴰ ⴰ.",
        "userpage-userdoesnotexist-view": "ⴰⵎⵉⴹⴰⵏ ⵏ ⵓⵎⵙⵙⵎⵔⵙ $1 ⵓⵔ ⵉⵜⵜⵓⵣⵎⵎⴻⵎ.",
        "last": "ⵓⵣⵡⵔ",
        "page_last": "ⴰⵎⴳⴳⴰⵔⵓ",
        "histlegend": "ⴰⵙⵜⴰⵢ ⵏ ⵓⵎⵣⴰⵔⴰⵢ : ⵔⵛⵎ ⵜⴰⵏⴽⵓⵍⵉⵏ ⵏ ⵜⵓⵏⵖⵉⵍⵉⵏ ⵏⵏⴰ ⵜⵔⵉⴷ ⴰⴷ ⵜⵙⵎⵣⴰⵣⴰⵍⴷ ⵜⴰⴷⵔⴷ ⵉ ⴰⴽⵎ ⵏⵖ ⵉ ⵜⵙⴰⵔⵓⵜ ⵏ ⵢⵉⵣⴷⴰⵔ.<br />\nⵜⴰⴱⴰⴷⵓⵜ : <strong>({{int:cur}})</strong> = ⴰⵎⵣⴰⵔⴰⵢ ⴰⴽⴷ ⵜⵓⵏⵖⵉⵍⵜ ⵜⴰⵎⴳⴳⴰⵔⵓⵜ, <strong>({{int:last}})</strong> = ⴰⵎⵣⴰⵔⴰⵢ ⴰⴽⴷ ⵜⵓⵏⵖⵉⵍⵜ ⵉⵣⵔⵉⵏ, <strong>{{int:minoreditletter}}</strong> = ⵉⵙⵏⵉⴼⵉⵍⵏ ⵉⵎⵥⵥⵉⵢⵏ.",
-       "history-fieldset-title": "âµ\94âµ£âµ\93 âµ\96â´¼ ⵉⵣⵣⵔⴰⵢⵏ",
+       "history-fieldset-title": "âµ\99âµ\9câµ\89 ⵉⵣⵣⵔⴰⵢⵏ",
        "histfirst": "ⴰⵇⴱⵓⵔ",
        "histlast": "ⴰⵎⴰⵢⵏⵓ",
        "history-feed-title": "ⴰⵎⵣⵔⵓⵢ ⵏ ⵓⵣⵣⵔⴰⵢ",
        "rcfilters-savedqueries-already-saved": "ⵜⵉⵎⵣⵉⵣⴷⴳⵉⵜⵉⵏ ⴰⴷ ⵜⵜⵡⴰⵃⴹⴰⵏⵜ ⵢⴰⴷ. ⵙⵏⴼⵍ ⵜⵉⵙⵖⴰⵍ ⵏⴽ ⵃⵎⴰ ⴰⴷ ⵜⵙⵏⴼⵍⴷ ⵜⵉⵎⵣⵉⵣⴷⴳⵜ ⵜⴰⵎⴰⵢⵏⵓⵜ ⵉⵜⵜⵡⴰⵃⴹⴰⵏ.",
        "rcfilters-restore-default-filters": "ⵔⴰⵔ ⴷ ⵜⵉⵎⵣⵉⵣⴷⴳⵉⵜⵉⵏ ⵙ ⵓⵎⵕⴰⴹ",
        "rcfilters-clear-all-filters": "ⵚⵚⴼⴹ ⴰⴽⴽⵯ ⵜⵉⵎⵣⵉⵣⴷⴳⵉⵜⵉⵏ",
-       "rcfilters-show-new-changes": "ⵙⴽⵏ ⵉⵙⵏⴼⵍⵏ ⵉⵎⴰⵢⵏⵓⵜⵏ",
+       "rcfilters-show-new-changes": "ⵙⴽⵏ ⵉⵙⵏⴼⵍⵏ ⵉⵎⴰⵢⵏⵓⵜⵏ ⵣⴳ $1",
        "rcfilters-search-placeholder": "ⵣⵉⵣⴷⵉⴳ ⵉⵙⵏⴼⵍⵏ (ⵙⵎⵔⵙ ⵓⵎⵓⵖ ⵏⵖ ⵔⵣⵓ ⵖⴼ ⵉⵙⵎ ⵏ ⵜⵎⵣⵉⵣⴷⴳⵜ)",
        "rcfilters-invalid-filter": "ⵜⵉⵎⵣⵉⵣⴷⴳⵜ ⵓⵔ ⵉⵖⵥⴰⵏⵏ",
        "rcfilters-empty-filter": "ⵃⵜⵜⴰ ⴽⵔⴰ ⵏ ⵜⵉⵎⵣⵉⵣⴷⴳⵜ ⵉⵙⵡⵓⵔⵉⵏ. ⴰⴽⴽⵯ ⵉⵙⵏⵍⵏ ⵜⵜⵡⴰⵙⴽⵏⵏ.",
index 208449b..4ccd526 100644 (file)
        "editcomment": "編輯摘要為:<em>$1</em>。",
        "revertpage": "已還原[[Special:Contributions/$2|$2]]([[User talk:$2|討論]])的編輯至最後由[[User:$1|$1]]所修訂的版本",
        "revertpage-nouser": "已還原隱藏使用者的編輯為最後 {{GENDER:$1|[[User:$1|$1]]}} 修訂的版本",
-       "rollback-success": "已還原 {{GENDER:$3|$1}} 所做的編輯;\n變更回由 {{GENDER:$4|$2}} 修訂的最後一個版本。",
+       "rollback-success": "已還原{{GENDER:$3|$1}}所做的編輯;變更回由{{GENDER:$4|$2}}修訂的最後一個版本。",
        "sessionfailure-title": "連線階段失敗",
        "sessionfailure": "您的登入連線階段似乎有問題,為了預防連線階段受到劫持攻擊,此動作已經被取消。請重新提交表單。",
        "changecontentmodel": "變更頁面的內容模型",
        "logentry-import-upload": "$1 已由檔案上傳{{GENDER:$2|匯入}} $3",
        "logentry-import-upload-details": "$1 已使用檔案上傳{{GENDER:$2|匯入}} $3 ($4 {{PLURAL:$4|修訂|修訂}})",
        "logentry-import-interwiki": "$1 已由其他 wiki {{GENDER:$2|匯入}} $3",
-       "logentry-import-interwiki-details": "$1 已自 $5 {{GENDER:$2|匯入}} $3 ($4 {{PLURAL:$4|修訂|修訂}})",
+       "logentry-import-interwiki-details": "$1已自$5{{GENDER:$2|匯入}}$3($4{{PLURAL:$4|修訂|修訂}})",
        "logentry-merge-merge": "$1 將 $3 {{GENDER:$2|合併}}至 $4 (修訂版本至 $5)",
        "logentry-move-move": "$1 {{GENDER:$2|已移動}}頁面 $3 至 $4",
        "logentry-move-move-noredirect": "$1 {{GENDER:$2|已移動}}頁面 $3 至 $4,不留重新導向",
index 59e9c86..55bf54c 100644 (file)
@@ -9,3 +9,7 @@
  */
 
 $fallback = 'hy';
+
+$magicWords['redirect'] = [ '0', '#ՎԵՐԱՅՂՈՒՄ', '#ՎԵՐԱՀՂՈՒՄ', '#REDIRECT' ];
+
+$namespaceNames[NS_CATEGORY] = 'Ստորոգութիւն';
index 6edb7ec..3f0c3df 100644 (file)
--- a/load.php
+++ b/load.php
@@ -28,6 +28,8 @@ use MediaWiki\MediaWikiServices;
 // details of the session. Enforce this constraint with respect to session use.
 define( 'MW_NO_SESSION', 1 );
 
+define( 'MW_ENTRY_POINT', 'load' );
+
 require __DIR__ . '/includes/WebStart.php';
 
 // URL safety checks
index 6d6dbe5..f89fa62 100644 (file)
@@ -20,6 +20,8 @@
  * @defgroup Maintenance Maintenance
  */
 
+define( 'MW_ENTRY_POINT', 'cli' );
+
 // Bail on old versions of PHP, or if composer has not been run yet to install
 // dependencies.
 require_once __DIR__ . '/../includes/PHPVersionCheck.php';
diff --git a/maintenance/archives/patch-drop-user-fields.sql b/maintenance/archives/patch-drop-user-fields.sql
new file mode 100644 (file)
index 0000000..7faa593
--- /dev/null
@@ -0,0 +1,50 @@
+--
+-- patch-drop-user-fields.sql
+--
+-- T188327. Drop old xx_user and xx_user_text fields, and defaults from xx_actor fields.
+
+ALTER TABLE /*_*/archive
+  DROP INDEX /*i*/ar_usertext_timestamp,
+  DROP COLUMN ar_user,
+  DROP COLUMN ar_user_text,
+  ALTER COLUMN ar_actor DROP DEFAULT;
+
+ALTER TABLE /*_*/ipblocks
+  DROP COLUMN ipb_by,
+  DROP COLUMN ipb_by_text,
+  ALTER COLUMN ipb_by_actor DROP DEFAULT;
+
+ALTER TABLE /*_*/image
+  DROP INDEX /*i*/img_user_timestamp,
+  DROP INDEX /*i*/img_usertext_timestamp,
+  DROP COLUMN img_user,
+  DROP COLUMN img_user_text,
+  ALTER COLUMN img_actor DROP DEFAULT;
+
+ALTER TABLE /*_*/oldimage
+  DROP INDEX /*i*/oi_usertext_timestamp,
+  DROP COLUMN oi_user,
+  DROP COLUMN oi_user_text,
+  ALTER COLUMN oi_actor DROP DEFAULT;
+
+ALTER TABLE /*_*/filearchive
+  DROP INDEX /*i*/fa_user_timestamp,
+  DROP COLUMN fa_user,
+  DROP COLUMN fa_user_text,
+  ALTER COLUMN fa_actor DROP DEFAULT;
+
+ALTER TABLE /*_*/recentchanges
+  DROP INDEX /*i*/rc_ns_usertext,
+  DROP INDEX /*i*/rc_user_text,
+  DROP COLUMN rc_user,
+  DROP COLUMN rc_user_text,
+  ALTER COLUMN rc_actor DROP DEFAULT;
+
+ALTER TABLE /*_*/logging
+  DROP INDEX /*i*/user_time,
+  DROP INDEX /*i*/log_user_type_time,
+  DROP INDEX /*i*/log_user_text_type_time,
+  DROP INDEX /*i*/log_user_text_time,
+  DROP COLUMN log_user,
+  DROP COLUMN log_user_text,
+  ALTER COLUMN log_actor DROP DEFAULT;
index 305a41d..6928181 100644 (file)
@@ -42,6 +42,9 @@ class CleanupImages extends TableCleanup {
                'callback' => 'processRow',
        ];
 
+       /** @var LocalRepo|null */
+       private $repo;
+
        public function __construct() {
                parent::__construct();
                $this->addDescription( 'Script to clean up broken, unparseable upload filenames' );
@@ -111,8 +114,12 @@ class CleanupImages extends TableCleanup {
                }
        }
 
+       /**
+        * @param string $name
+        * @return string
+        */
        private function filePath( $name ) {
-               if ( !isset( $this->repo ) ) {
+               if ( $this->repo === null ) {
                        $this->repo = RepoGroup::singleton()->getLocalRepo();
                }
 
index cad6122..5602e39 100644 (file)
@@ -133,7 +133,7 @@ class TitleCleanup extends TableCleanup {
         * @param Title $title
         */
        protected function moveInconsistentPage( $row, Title $title ) {
-               if ( $title->exists( Title::GAID_FOR_UPDATE )
+               if ( $title->exists( Title::READ_LATEST )
                        || $title->getInterwiki()
                        || !$title->canExist()
                ) {
index 3f55878..0d4b7b1 100644 (file)
@@ -39,6 +39,18 @@ require_once __DIR__ . '/dumpIterator.php';
 class CompareParsers extends DumpIterator {
 
        private $count = 0;
+       /** @var bool */
+       private $saveFailed;
+       /** @var bool */
+       private $stripParametersEnabled;
+       /** @var bool */
+       private $showParsedOutput;
+       /** @var bool */
+       private $showDiff;
+       /** @var ParserOptions */
+       private $options;
+       /** @var int */
+       private $failed;
 
        public function __construct() {
                parent::__construct();
index 751932d..20e9459 100644 (file)
@@ -34,9 +34,10 @@ require_once __DIR__ . '/Maintenance.php';
  * @ingroup Maintenance
  */
 abstract class DumpIterator extends Maintenance {
-
        private $count = 0;
        private $startTime;
+       /** @var string|bool|null */
+       private $from;
 
        public function __construct() {
                parent::__construct();
@@ -60,6 +61,7 @@ abstract class DumpIterator extends Maintenance {
                        $revision->setTitle( Title::newFromText(
                                rawurldecode( basename( $this->getOption( 'file' ), '.txt' ) )
                        ) );
+                       $this->from = false;
                        $this->handleRevision( $revision );
 
                        return;
@@ -131,7 +133,7 @@ abstract class DumpIterator extends Maintenance {
                }
 
                $this->count++;
-               if ( isset( $this->from ) ) {
+               if ( $this->from !== false ) {
                        if ( $this->from != $title ) {
                                return;
                        }
index d861348..7e9104c 100644 (file)
@@ -38,9 +38,7 @@ class GetReplicaServer extends Maintenance {
        }
 
        public function execute() {
-               if ( $this->getConfig()->get( 'AllDBsAreLocalhost' ) ) {
-                       $host = 'localhost';
-               } elseif ( $this->hasOption( 'group' ) ) {
+               if ( $this->hasOption( 'group' ) ) {
                        $db = $this->getDB( DB_REPLICA, $this->getOption( 'group' ) );
                        $host = $db->getServer();
                } else {
index cda16fe..d5f94ad 100644 (file)
@@ -43,6 +43,16 @@ class BackupReader extends Maintenance {
        public $imageBasePath = false;
        /** @var array|false */
        public $nsFilter = false;
+       /** @var bool|resource */
+       public $stderr;
+       /** @var callable|null */
+       protected $importCallback;
+       /** @var callable|null */
+       protected $logItemCallback;
+       /** @var callable|null */
+       protected $uploadCallback;
+       /** @var int */
+       protected $startTime;
 
        function __construct() {
                parent::__construct();
index 358dc21..6c1c083 100644 (file)
@@ -49,6 +49,8 @@ abstract class BackupDumper extends Maintenance {
        public $dumpUploadFileContents = false;
        public $orderRevs = false;
        public $limitNamespaces = [];
+       /** @var bool|resource */
+       public $stderr;
 
        protected $reportingInterval = 100;
        protected $pageCount = 0;
@@ -65,6 +67,33 @@ abstract class BackupDumper extends Maintenance {
 
        protected $ID = 0;
 
+       /** @var int */
+       protected $startTime;
+       /** @var int */
+       protected $pageCountPart;
+       /** @var int */
+       protected $revCountPart;
+       /** @var int */
+       protected $maxCount;
+       /** @var int */
+       protected $timeOfCheckpoint;
+       /** @var ExportProgressFilter */
+       protected $egress;
+       /** @var string */
+       protected $buffer;
+       /** @var array|false */
+       protected $openElement;
+       /** @var bool */
+       protected $atStart;
+       /** @var string|null */
+       protected $thisRevModel;
+       /** @var string|null */
+       protected $thisRevFormat;
+       /** @var string */
+       protected $lastName;
+       /** @var string */
+       protected $state;
+
        /**
         * The dependency-injected database to use.
         *
index 1b35a20..48dcf8d 100644 (file)
@@ -51,15 +51,6 @@ class MigrateActors extends LoggedUpdateMaintenance {
        }
 
        protected function doDBUpdates() {
-               $actorTableSchemaMigrationStage = $this->getConfig()->get( 'ActorTableSchemaMigrationStage' );
-
-               if ( !( $actorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) ) {
-                       $this->output(
-                               "...cannot update while \$wgActorTableSchemaMigrationStage lacks SCHEMA_COMPAT_WRITE_NEW\n"
-                       );
-                       return false;
-               }
-
                $tables = $this->getOption( 'tables' );
                if ( $tables !== null ) {
                        $this->tables = explode( ',', $tables );
@@ -265,6 +256,12 @@ class MigrateActors extends LoggedUpdateMaintenance {
                        return 0;
                }
 
+               $dbw = $this->getDB( DB_MASTER );
+               if ( !$dbw->fieldExists( $table, $userField, __METHOD__ ) ) {
+                       $this->output( "No need to migrate $table.$userField, field does not exist\n" );
+                       return 0;
+               }
+
                $complainedAboutUsers = [];
 
                $primaryKey = (array)$primaryKey;
@@ -274,7 +271,6 @@ class MigrateActors extends LoggedUpdateMaintenance {
                );
                wfWaitForSlaves();
 
-               $dbw = $this->getDB( DB_MASTER );
                $actorIdSubquery = $this->makeActorIdSubquery( $dbw, $userField, $nameField );
                $next = '1=1';
                $countUpdated = 0;
@@ -357,6 +353,7 @@ class MigrateActors extends LoggedUpdateMaintenance {
         * @param string $nameField User name field name
         * @param string $newPrimaryKey Primary key of the new table.
         * @param string $actorField Actor field name
+        * @return int Number of errors
         */
        protected function migrateToTemp(
                $table, $primaryKey, $extra, $userField, $nameField, $newPrimaryKey, $actorField
@@ -366,6 +363,12 @@ class MigrateActors extends LoggedUpdateMaintenance {
                        return 0;
                }
 
+               $dbw = $this->getDB( DB_MASTER );
+               if ( !$dbw->fieldExists( $table, $userField, __METHOD__ ) ) {
+                       $this->output( "No need to migrate $table.$userField, field does not exist\n" );
+                       return 0;
+               }
+
                $complainedAboutUsers = [];
 
                $newTable = $table . '_actor_temp';
@@ -374,7 +377,6 @@ class MigrateActors extends LoggedUpdateMaintenance {
                );
                wfWaitForSlaves();
 
-               $dbw = $this->getDB( DB_MASTER );
                $actorIdSubquery = $this->makeActorIdSubquery( $dbw, $userField, $nameField );
                $next = [];
                $countUpdated = 0;
index a71bb74..16b8ccf 100644 (file)
@@ -118,7 +118,7 @@ class CommandLineInstaller extends Maintenance {
                try {
                        $installer = InstallerOverrides::getCliInstaller( $siteName, $adminName, $this->mOptions );
                } catch ( \MediaWiki\Installer\InstallException $e ) {
-                       $this->output( $e->getStatus()->getMessage()->parse() . "\n" );
+                       $this->output( $e->getStatus()->getMessage()->text() . "\n" );
                        return false;
                }
 
@@ -133,6 +133,8 @@ class CommandLineInstaller extends Maintenance {
                if ( !$envChecksOnly ) {
                        $status = $installer->execute();
                        if ( !$status->isGood() ) {
+                               $installer->showStatusMessage( $status );
+
                                return false;
                        }
                        $installer->writeConfigurationFile( $this->getOption( 'confpath', $IP ) );
index 4a50cc5..4401ea8 100644 (file)
@@ -42,6 +42,26 @@ require_once __DIR__ . '/Maintenance.php';
  * @ingroup Maintenance
  */
 class MWDocGen extends Maintenance {
+       /** @var string */
+       private $doxygen;
+       /** @var string */
+       private $mwVersion;
+       /** @var string */
+       private $output;
+       /** @var string */
+       private $input;
+       /** @var string */
+       private $inputFilter;
+       /** @var string */
+       private $template;
+       /** @var string[] */
+       private $excludes;
+       /** @var string[] */
+       private $excludePatterns;
+       /** @var bool */
+       private $doDot;
+       /** @var bool */
+       private $doMan;
 
        /**
         * Prepare Maintenance class
@@ -100,10 +120,17 @@ class MWDocGen extends Maintenance {
                        'resources/lib',
                        'images',
                        'static',
+                       'tests',
+                       'includes/libs/Message/README.md',
+                       'includes/libs/objectcache/README.md',
+                       'includes/libs/ParamValidator/README.md',
+                       'maintenance/benchmarks/README.md',
+                       'resources/src/mediawiki.ui/styleguide.md',
                ];
                $this->excludePatterns = [];
                if ( $this->hasOption( 'no-extensions' ) ) {
                        $this->excludePatterns[] = 'extensions';
+                       $this->excludePatterns[] = 'skins';
                }
 
                $this->doDot = shell_exec( 'which dot' );
index 87fb396..20096a2 100644 (file)
@@ -244,9 +244,7 @@ CREATE TABLE archive (
   ar_parent_id      INTEGER          NULL,
   ar_sha1           TEXT         NOT NULL DEFAULT '',
   ar_comment_id     INTEGER      NOT NULL,
-  ar_user           INTEGER      NOT NULL DEFAULT 0 REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
-  ar_user_text      TEXT         NOT NULL DEFAULT '',
-  ar_actor          INTEGER      NOT NULL DEFAULT 0,
+  ar_actor          INTEGER      NOT NULL,
   ar_timestamp      TIMESTAMPTZ  NOT NULL,
   ar_minor_edit     SMALLINT     NOT NULL  DEFAULT 0,
   ar_rev_id         INTEGER      NOT NULL,
@@ -258,7 +256,6 @@ CREATE TABLE archive (
 );
 ALTER SEQUENCE archive_ar_id_seq OWNED BY archive.ar_id;
 CREATE INDEX archive_name_title_timestamp ON archive (ar_namespace,ar_title,ar_timestamp);
-CREATE INDEX archive_user_text            ON archive (ar_user_text);
 CREATE INDEX archive_actor                ON archive (ar_actor);
 CREATE UNIQUE INDEX ar_revid_uniq ON archive (ar_rev_id);
 
@@ -404,9 +401,7 @@ CREATE TABLE ipblocks (
   ipb_id                INTEGER      NOT NULL  PRIMARY KEY DEFAULT nextval('ipblocks_ipb_id_seq'),
   ipb_address           TEXT             NULL,
   ipb_user              INTEGER          NULL  REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
-  ipb_by                INTEGER      NOT NULL  DEFAULT 0 REFERENCES mwuser(user_id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
-  ipb_by_text           TEXT         NOT NULL  DEFAULT '',
-  ipb_by_actor          INTEGER      NOT NULL  DEFAULT 0,
+  ipb_by_actor          INTEGER      NOT NULL,
   ipb_reason_id         INTEGER      NOT NULL,
   ipb_timestamp         TIMESTAMPTZ  NOT NULL,
   ipb_auto              SMALLINT     NOT NULL  DEFAULT 0,
@@ -448,9 +443,7 @@ CREATE TABLE image (
   img_major_mime   TEXT                DEFAULT 'unknown',
   img_minor_mime   TEXT                DEFAULT 'unknown',
   img_description_id INTEGER NOT NULL,
-  img_user         INTEGER   NOT NULL  DEFAULT 0 REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
-  img_user_text    TEXT      NOT NULL  DEFAULT '',
-  img_actor        INTEGER   NOT NULL  DEFAULT 0,
+  img_actor        INTEGER   NOT NULL,
   img_timestamp    TIMESTAMPTZ,
   img_sha1         TEXT      NOT NULL  DEFAULT ''
 );
@@ -466,9 +459,7 @@ CREATE TABLE oldimage (
   oi_height        INTEGER      NOT NULL,
   oi_bits          SMALLINT         NULL,
   oi_description_id INTEGER     NOT NULL,
-  oi_user          INTEGER      NOT NULL DEFAULT 0  REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
-  oi_user_text     TEXT         NOT NULL DEFAULT '',
-  oi_actor         INTEGER      NOT NULL DEFAULT 0,
+  oi_actor         INTEGER      NOT NULL,
   oi_timestamp     TIMESTAMPTZ      NULL,
   oi_metadata      BYTEA        NOT NULL DEFAULT '',
   oi_media_type    TEXT             NULL,
@@ -502,9 +493,7 @@ CREATE TABLE filearchive (
   fa_major_mime         TEXT                   DEFAULT 'unknown',
   fa_minor_mime         TEXT                   DEFAULT 'unknown',
   fa_description_id     INTEGER      NOT NULL,
-  fa_user               INTEGER      NOT NULL DEFAULT 0 REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
-  fa_user_text          TEXT         NOT NULL DEFAULT '',
-  fa_actor              INTEGER      NOT NULL DEFAULT 0,
+  fa_actor              INTEGER      NOT NULL,
   fa_timestamp          TIMESTAMPTZ,
   fa_deleted            SMALLINT     NOT NULL DEFAULT 0,
   fa_sha1               TEXT         NOT NULL DEFAULT ''
@@ -548,9 +537,7 @@ CREATE SEQUENCE recentchanges_rc_id_seq;
 CREATE TABLE recentchanges (
   rc_id              INTEGER      NOT NULL  PRIMARY KEY DEFAULT nextval('recentchanges_rc_id_seq'),
   rc_timestamp       TIMESTAMPTZ  NOT NULL,
-  rc_user            INTEGER      NOT NULL  DEFAULT 0 REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
-  rc_user_text       TEXT         NOT NULL  DEFAULT '',
-  rc_actor           INTEGER      NOT NULL  DEFAULT 0,
+  rc_actor           INTEGER      NOT NULL,
   rc_namespace       SMALLINT     NOT NULL,
   rc_title           TEXT         NOT NULL,
   rc_comment_id      INTEGER      NOT NULL,
@@ -646,27 +633,21 @@ CREATE TABLE logging (
   log_type        TEXT         NOT NULL,
   log_action      TEXT         NOT NULL,
   log_timestamp   TIMESTAMPTZ  NOT NULL,
-  log_user        INTEGER      NOT NULL DEFAULT 0 REFERENCES mwuser(user_id) ON DELETE SET NULL DEFERRABLE INITIALLY DEFERRED,
-  log_actor       INTEGER      NOT NULL DEFAULT 0,
+  log_actor       INTEGER      NOT NULL,
   log_namespace   SMALLINT     NOT NULL,
   log_title       TEXT         NOT NULL,
   log_comment_id  INTEGER      NOT NULL,
   log_params      TEXT,
   log_deleted     SMALLINT     NOT NULL DEFAULT 0,
-  log_user_text   TEXT         NOT NULL DEFAULT '',
   log_page        INTEGER
 );
 ALTER SEQUENCE logging_log_id_seq OWNED BY logging.log_id;
 CREATE INDEX logging_type_name ON logging (log_type, log_timestamp);
-CREATE INDEX logging_user_time ON logging (log_timestamp, log_user);
 CREATE INDEX logging_actor_time_backwards ON logging (log_timestamp, log_actor);
 CREATE INDEX logging_page_time ON logging (log_namespace, log_title, log_timestamp);
 CREATE INDEX logging_times ON logging (log_timestamp);
-CREATE INDEX logging_user_type_time ON logging (log_user, log_type, log_timestamp);
 CREATE INDEX logging_actor_type_time ON logging (log_actor, log_type, log_timestamp);
 CREATE INDEX logging_page_id_time ON logging (log_page, log_timestamp);
-CREATE INDEX logging_user_text_type_time ON logging (log_user_text, log_type, log_timestamp);
-CREATE INDEX logging_user_text_time ON logging (log_user_text, log_timestamp);
 CREATE INDEX logging_actor_time ON logging (log_actor, log_timestamp);
 CREATE INDEX logging_type_action ON logging (log_type, log_action, log_timestamp);
 
index 05b78d4..fddac8a 100644 (file)
@@ -41,6 +41,8 @@ class PreprocessDump extends DumpIterator {
        /* Variables for dressing up as a parser */
        public $mTitle = 'PreprocessDump';
        public $mPPNodeCount = 0;
+       /** @var Preprocessor */
+       public $mPreprocessor;
 
        public function getStripList() {
                $parser = MediaWikiServices::getInstance()->getParser();
index 68fb643..3a43ae8 100644 (file)
@@ -150,6 +150,16 @@ class PPFuzzTester {
 class PPFuzzTest {
        public $templates, $mainText, $title, $entryPoint, $output;
 
+       /** @var PPFuzzTester */
+       private $parent;
+       /** @var string */
+       public $nickname;
+       /** @var bool */
+       public $fancySig;
+
+       /**
+        * @param PPFuzzTester $tester
+        */
        function __construct( $tester ) {
                global $wgMaxSigChars;
                $this->parent = $tester;
index 54f1862..f3b856c 100644 (file)
@@ -23,8 +23,6 @@
  * @license GPL-2.0-or-later
  */
 
-use Wikimedia\Rdbms\IDatabase;
-
 require_once __DIR__ . '/Maintenance.php';
 
 /**
@@ -76,8 +74,6 @@ class ReassignEdits extends Maintenance {
         * @return int Number of entries changed, or that would be changed
         */
        private function doReassignEdits( &$from, &$to, $rc = false, $report = false ) {
-               $actorTableSchemaMigrationStage = $this->getConfig()->get( 'ActorTableSchemaMigrationStage' );
-
                $dbw = $this->getDB( DB_MASTER );
                $this->beginTransaction( $dbw, __METHOD__ );
 
@@ -136,36 +132,22 @@ class ReassignEdits extends Maintenance {
                        if ( $total ) {
                                # Reassign edits
                                $this->output( "\nReassigning current edits..." );
-                               if ( $actorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
-                                       $dbw->update(
-                                               'revision',
-                                               [
-                                                       'rev_user' => $to->getId(),
-                                                       'rev_user_text' => $to->getName(),
-                                               ],
-                                               $from->isLoggedIn()
-                                                       ? [ 'rev_user' => $from->getId() ] : [ 'rev_user_text' => $from->getName() ],
-                                               __METHOD__
-                                       );
-                               }
-                               if ( $actorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                                       $dbw->update(
-                                               'revision_actor_temp',
-                                               [ 'revactor_actor' => $to->getActorId( $dbw ) ],
-                                               [ 'revactor_actor' => $from->getActorId() ],
-                                               __METHOD__
-                                       );
-                               }
+                               $dbw->update(
+                                       'revision_actor_temp',
+                                       [ 'revactor_actor' => $to->getActorId( $dbw ) ],
+                                       [ 'revactor_actor' => $from->getActorId() ],
+                                       __METHOD__
+                               );
                                $this->output( "done.\nReassigning deleted edits..." );
                                $dbw->update( 'archive',
-                                       $this->userSpecification( $dbw, $to, 'ar_user', 'ar_user_text', 'ar_actor' ),
+                                       [ 'ar_actor' => $to->getActorId( $dbw ) ],
                                        [ $arQueryInfo['conds'] ], __METHOD__ );
                                $this->output( "done.\n" );
                                # Update recent changes if required
                                if ( $rc ) {
                                        $this->output( "Updating recent changes..." );
                                        $dbw->update( 'recentchanges',
-                                               $this->userSpecification( $dbw, $to, 'rc_user', 'rc_user_text', 'rc_actor' ),
+                                               [ 'rc_actor' => $to->getActorId( $dbw ) ],
                                                [ $rcQueryInfo['conds'] ], __METHOD__ );
                                        $this->output( "done.\n" );
                                }
@@ -177,33 +159,6 @@ class ReassignEdits extends Maintenance {
                return (int)$total;
        }
 
-       /**
-        * Return user specifications for an UPDATE
-        * i.e. user => id, user_text => text
-        *
-        * @param IDatabase $dbw Database handle
-        * @param User $user User for the spec
-        * @param string $idfield Field name containing the identifier
-        * @param string $utfield Field name containing the user text
-        * @param string $acfield Field name containing the actor ID
-        * @return array
-        */
-       private function userSpecification( IDatabase $dbw, &$user, $idfield, $utfield, $acfield ) {
-               $actorTableSchemaMigrationStage = $this->getConfig()->get( 'ActorTableSchemaMigrationStage' );
-
-               $ret = [];
-               if ( $actorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
-                       $ret += [
-                               $idfield => $user->getId(),
-                               $utfield => $user->getName(),
-                       ];
-               }
-               if ( $actorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                       $ret += [ $acfield => $user->getActorId( $dbw ) ];
-               }
-               return $ret;
-       }
-
        /**
         * Initialise the user object
         *
index bfbee9b..df2ab04 100644 (file)
@@ -41,12 +41,32 @@ use Wikimedia\Rdbms\IMaintainableDatabase;
  * @ingroup Maintenance
  */
 class ImageBuilder extends Maintenance {
-
        /**
         * @var IMaintainableDatabase
         */
        protected $dbw;
 
+       /** @var bool */
+       private $dryrun;
+
+       /** @var LocalRepo|null */
+       private $repo;
+
+       /** @var int */
+       private $updated;
+
+       /** @var int */
+       private $processed;
+
+       /** @var int */
+       private $count;
+
+       /** @var int */
+       private $startTime;
+
+       /** @var string */
+       private $table;
+
        function __construct() {
                parent::__construct();
 
@@ -79,7 +99,7 @@ class ImageBuilder extends Maintenance {
         * @return LocalRepo
         */
        function getRepo() {
-               if ( !isset( $this->repo ) ) {
+               if ( $this->repo === null ) {
                        $this->repo = RepoGroup::singleton()->getLocalRepo();
                }
 
@@ -91,6 +111,10 @@ class ImageBuilder extends Maintenance {
                $this->buildOldImage();
        }
 
+       /**
+        * @param int $count
+        * @param string $table
+        */
        function init( $count, $table ) {
                $this->processed = 0;
                $this->updated = 0;
index 7e8f063..8ec648f 100644 (file)
@@ -36,6 +36,12 @@ use MediaWiki\MediaWikiServices;
  * @ingroup Maintenance
  */
 class RecountCategories extends Maintenance {
+       /** @var string */
+       private $mode;
+
+       /** @var int */
+       private $minimumId;
+
        public function __construct() {
                parent::__construct();
                $this->addDescription( <<<'TEXT'
index 16a7346..ca90468 100644 (file)
@@ -39,8 +39,6 @@ class RemoveUnusedAccounts extends Maintenance {
        }
 
        public function execute() {
-               $actorTableSchemaMigrationStage = $this->getConfig()->get( 'ActorTableSchemaMigrationStage' );
-
                $this->output( "Remove unused accounts\n\n" );
 
                # Do an initial scan for inactive accounts and report the result
@@ -48,18 +46,14 @@ class RemoveUnusedAccounts extends Maintenance {
                $delUser = [];
                $delActor = [];
                $dbr = $this->getDB( DB_REPLICA );
-               if ( $actorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                       $res = $dbr->select(
-                               [ 'user', 'actor' ],
-                               [ 'user_id', 'user_name', 'user_touched', 'actor_id' ],
-                               '',
-                               __METHOD__,
-                               [],
-                               [ 'actor' => [ 'LEFT JOIN', 'user_id = actor_user' ] ]
-                       );
-               } else {
-                       $res = $dbr->select( 'user', [ 'user_id', 'user_name', 'user_touched' ], '', __METHOD__ );
-               }
+               $res = $dbr->select(
+                       [ 'user', 'actor' ],
+                       [ 'user_id', 'user_name', 'user_touched', 'actor_id' ],
+                       '',
+                       __METHOD__,
+                       [],
+                       [ 'actor' => [ 'LEFT JOIN', 'user_id = actor_user' ] ]
+               );
                if ( $this->hasOption( 'ignore-groups' ) ) {
                        $excludedGroups = explode( ',', $this->getOption( 'ignore-groups' ) );
                } else {
@@ -94,30 +88,22 @@ class RemoveUnusedAccounts extends Maintenance {
                        $this->output( "\nDeleting unused accounts..." );
                        $dbw = $this->getDB( DB_MASTER );
                        $dbw->delete( 'user', [ 'user_id' => $delUser ], __METHOD__ );
-                       if ( $actorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                               # Keep actor rows referenced from ipblocks
-                               $keep = $dbw->selectFieldValues(
-                                       'ipblocks', 'ipb_by_actor', [ 'ipb_by_actor' => $delActor ], __METHOD__
-                               );
-                               $del = array_diff( $delActor, $keep );
-                               if ( $del ) {
-                                       $dbw->delete( 'actor', [ 'actor_id' => $del ], __METHOD__ );
-                               }
-                               if ( $keep ) {
-                                       $dbw->update( 'actor', [ 'actor_user' => 0 ], [ 'actor_id' => $keep ], __METHOD__ );
-                               }
+                       # Keep actor rows referenced from ipblocks
+                       $keep = $dbw->selectFieldValues(
+                               'ipblocks', 'ipb_by_actor', [ 'ipb_by_actor' => $delActor ], __METHOD__
+                       );
+                       $del = array_diff( $delActor, $keep );
+                       if ( $del ) {
+                               $dbw->delete( 'actor', [ 'actor_id' => $del ], __METHOD__ );
+                       }
+                       if ( $keep ) {
+                               $dbw->update( 'actor', [ 'actor_user' => 0 ], [ 'actor_id' => $keep ], __METHOD__ );
                        }
                        $dbw->delete( 'user_groups', [ 'ug_user' => $delUser ], __METHOD__ );
                        $dbw->delete( 'user_former_groups', [ 'ufg_user' => $delUser ], __METHOD__ );
                        $dbw->delete( 'user_properties', [ 'up_user' => $delUser ], __METHOD__ );
-                       if ( $actorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                               $dbw->delete( 'logging', [ 'log_actor' => $delActor ], __METHOD__ );
-                               $dbw->delete( 'recentchanges', [ 'rc_actor' => $delActor ], __METHOD__ );
-                       }
-                       if ( $actorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_OLD ) {
-                               $dbw->delete( 'logging', [ 'log_user' => $delUser ], __METHOD__ );
-                               $dbw->delete( 'recentchanges', [ 'rc_user' => $delUser ], __METHOD__ );
-                       }
+                       $dbw->delete( 'logging', [ 'log_actor' => $delActor ], __METHOD__ );
+                       $dbw->delete( 'recentchanges', [ 'rc_actor' => $delActor ], __METHOD__ );
                        $this->output( "done.\n" );
                        # Update the site_stats.ss_users field
                        $users = $dbw->selectField( 'user', 'COUNT(*)', [], __METHOD__ );
index cc5ae59..85795ca 100644 (file)
@@ -40,6 +40,8 @@ class DumpRenderer extends Maintenance {
 
        private $count = 0;
        private $outputDirectory, $startTime;
+       /** @var string */
+       private $prefix;
 
        public function __construct() {
                parent::__construct();
diff --git a/maintenance/sqlite/archives/patch-archive-drop-ar_user.sql b/maintenance/sqlite/archives/patch-archive-drop-ar_user.sql
new file mode 100644 (file)
index 0000000..ceb7d7d
--- /dev/null
@@ -0,0 +1,44 @@
+--
+-- patch-archive-drop-ar_user.sql
+--
+-- T188327. Drop old xx_user and xx_user_text fields, and defaults from xx_actor fields.
+
+BEGIN;
+
+DROP TABLE IF EXISTS /*_*/archive_tmp;
+CREATE TABLE /*_*/archive_tmp (
+  ar_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  ar_namespace int NOT NULL default 0,
+  ar_title varchar(255) binary NOT NULL default '',
+  ar_comment_id bigint unsigned NOT NULL,
+  ar_actor bigint unsigned NOT NULL,
+  ar_timestamp binary(14) NOT NULL default '',
+  ar_minor_edit tinyint NOT NULL default 0,
+  ar_rev_id int unsigned NOT NULL,
+  ar_text_id int unsigned NOT NULL DEFAULT 0,
+  ar_deleted tinyint unsigned NOT NULL default 0,
+  ar_len int unsigned,
+  ar_page_id int unsigned,
+  ar_parent_id int unsigned default NULL,
+  ar_sha1 varbinary(32) NOT NULL default '',
+  ar_content_model varbinary(32) DEFAULT NULL,
+  ar_content_format varbinary(64) DEFAULT NULL
+) /*$wgDBTableOptions*/;
+
+INSERT OR IGNORE INTO /*_*/archive_tmp (
+       ar_id, ar_namespace, ar_title, ar_comment_id, ar_actor,
+       ar_timestamp, ar_minor_edit, ar_rev_id, ar_text_id, ar_deleted,
+       ar_len, ar_page_id, ar_parent_id, ar_sha1, ar_content_model, ar_content_format
+  ) SELECT
+       ar_id, ar_namespace, ar_title, ar_comment_id, ar_actor,
+       ar_timestamp, ar_minor_edit, ar_rev_id, ar_text_id, ar_deleted,
+       ar_len, ar_page_id, ar_parent_id, ar_sha1, ar_content_model, ar_content_format
+  FROM /*_*/archive;
+
+DROP TABLE /*_*/archive;
+ALTER TABLE /*_*/archive_tmp RENAME TO /*_*/archive;
+CREATE INDEX /*i*/name_title_timestamp ON /*_*/archive (ar_namespace,ar_title,ar_timestamp);
+CREATE INDEX /*i*/ar_actor_timestamp ON /*_*/archive (ar_actor,ar_timestamp);
+CREATE UNIQUE INDEX /*i*/ar_revid_uniq ON /*_*/archive (ar_rev_id);
+
+COMMIT;
diff --git a/maintenance/sqlite/archives/patch-filearchive-drop-fa_user.sql b/maintenance/sqlite/archives/patch-filearchive-drop-fa_user.sql
new file mode 100644 (file)
index 0000000..0a20a56
--- /dev/null
@@ -0,0 +1,55 @@
+--
+-- patch-filearchive-drop-fa_user.sql
+--
+-- T188327. Drop old xx_user and xx_user_text fields, and defaults from xx_actor fields.
+
+BEGIN;
+
+DROP TABLE IF EXISTS /*_*/filearchive_tmp;
+CREATE TABLE /*_*/filearchive_tmp (
+  fa_id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  fa_name varchar(255) binary NOT NULL default '',
+  fa_archive_name varchar(255) binary default '',
+  fa_storage_group varbinary(16),
+  fa_storage_key varbinary(64) default '',
+  fa_deleted_user int,
+  fa_deleted_timestamp binary(14) default '',
+  fa_deleted_reason_id bigint unsigned NOT NULL,
+  fa_size int unsigned default 0,
+  fa_width int default 0,
+  fa_height int default 0,
+  fa_metadata mediumblob,
+  fa_bits int default 0,
+  fa_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D") default NULL,
+  fa_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical") default "unknown",
+  fa_minor_mime varbinary(100) default "unknown",
+  fa_description_id bigint unsigned NOT NULL,
+  fa_actor bigint unsigned NOT NULL DEFAULT 0,
+  fa_timestamp binary(14) default '',
+  fa_deleted tinyint unsigned NOT NULL default 0,
+  fa_sha1 varbinary(32) NOT NULL default ''
+) /*$wgDBTableOptions*/;
+
+INSERT OR IGNORE INTO /*_*/filearchive_tmp (
+       fa_id, fa_name, fa_archive_name, fa_storage_group, fa_storage_key,
+       fa_deleted_user, fa_deleted_timestamp, fa_deleted_reason_id,
+       fa_size, fa_width, fa_height, fa_metadata, fa_bits,
+       fa_media_type, fa_major_mime, fa_minor_mime, fa_description_id,
+       fa_actor, fa_timestamp, fa_deleted, fa_sha1
+  ) SELECT
+       fa_id, fa_name, fa_archive_name, fa_storage_group, fa_storage_key,
+       fa_deleted_user, fa_deleted_timestamp, fa_deleted_reason_id,
+       fa_size, fa_width, fa_height, fa_metadata, fa_bits,
+       fa_media_type, fa_major_mime, fa_minor_mime, fa_description_id,
+       fa_actor, fa_timestamp, fa_deleted, fa_sha1
+  FROM /*_*/filearchive;
+
+DROP TABLE /*_*/filearchive;
+ALTER TABLE /*_*/filearchive_tmp RENAME TO /*_*/filearchive;
+CREATE INDEX /*i*/fa_name ON /*_*/filearchive (fa_name, fa_timestamp);
+CREATE INDEX /*i*/fa_storage_group ON /*_*/filearchive (fa_storage_group, fa_storage_key);
+CREATE INDEX /*i*/fa_deleted_timestamp ON /*_*/filearchive (fa_deleted_timestamp);
+CREATE INDEX /*i*/fa_actor_timestamp ON /*_*/filearchive (fa_actor,fa_timestamp);
+CREATE INDEX /*i*/fa_sha1 ON /*_*/filearchive (fa_sha1(10));
+
+COMMIT;
diff --git a/maintenance/sqlite/archives/patch-image-drop-img_user.sql b/maintenance/sqlite/archives/patch-image-drop-img_user.sql
new file mode 100644 (file)
index 0000000..d93e122
--- /dev/null
@@ -0,0 +1,43 @@
+--
+-- patch-image-drop-img_description.sql
+--
+-- T188327. Drop old xx_user and xx_user_text fields, and defaults from xx_actor fields.
+
+BEGIN;
+
+DROP TABLE IF EXISTS /*_*/image_tmp;
+CREATE TABLE /*_*/image_tmp (
+  img_name varchar(255) binary NOT NULL default '' PRIMARY KEY,
+  img_size int unsigned NOT NULL default 0,
+  img_width int NOT NULL default 0,
+  img_height int NOT NULL default 0,
+  img_metadata mediumblob NOT NULL,
+  img_bits int NOT NULL default 0,
+  img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D") default NULL,
+  img_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical") NOT NULL default "unknown",
+  img_minor_mime varbinary(100) NOT NULL default "unknown",
+  img_description_id bigint unsigned NOT NULL,
+  img_actor bigint unsigned NOT NULL,
+  img_timestamp varbinary(14) NOT NULL default '',
+  img_sha1 varbinary(32) NOT NULL default ''
+) /*$wgDBTableOptions*/;
+
+INSERT OR IGNORE INTO /*_*/image_tmp (
+       img_name, img_size, img_width, img_height, img_metadata, img_bits,
+       img_media_type, img_major_mime, img_minor_mime, img_description_id,
+       img_actor, img_timestamp, img_sha1
+  ) SELECT
+       img_name, img_size, img_width, img_height, img_metadata, img_bits,
+       img_media_type, img_major_mime, img_minor_mime, img_description_id,
+       img_actor, img_timestamp, img_sha1
+  FROM /*_*/image;
+
+DROP TABLE /*_*/image;
+ALTER TABLE /*_*/image_tmp RENAME TO /*_*/image;
+CREATE INDEX /*i*/img_actor_timestamp ON /*_*/image (img_actor,img_timestamp);
+CREATE INDEX /*i*/img_size ON /*_*/image (img_size);
+CREATE INDEX /*i*/img_timestamp ON /*_*/image (img_timestamp);
+CREATE INDEX /*i*/img_sha1 ON /*_*/image (img_sha1(10));
+CREATE INDEX /*i*/img_media_mime ON /*_*/image (img_media_type,img_major_mime,img_minor_mime);
+
+COMMIT;
diff --git a/maintenance/sqlite/archives/patch-ipblocks-drop-ipb_by.sql b/maintenance/sqlite/archives/patch-ipblocks-drop-ipb_by.sql
new file mode 100644 (file)
index 0000000..2de5e09
--- /dev/null
@@ -0,0 +1,51 @@
+--
+-- patch-ipblocks-drop-ipb_by.sql
+--
+-- T188327. Drop old xx_user and xx_user_text fields, and defaults from xx_actor fields.
+
+BEGIN;
+
+DROP TABLE IF EXISTS ipblocks_tmp;
+CREATE TABLE /*_*/ipblocks_tmp (
+  ipb_id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  ipb_address tinyblob NOT NULL,
+  ipb_user int unsigned NOT NULL default 0,
+  ipb_by_actor bigint unsigned NOT NULL,
+  ipb_reason_id bigint unsigned NOT NULL,
+  ipb_timestamp binary(14) NOT NULL default '',
+  ipb_auto bool NOT NULL default 0,
+  ipb_anon_only bool NOT NULL default 0,
+  ipb_create_account bool NOT NULL default 1,
+  ipb_enable_autoblock bool NOT NULL default '1',
+  ipb_expiry varbinary(14) NOT NULL default '',
+  ipb_range_start tinyblob NOT NULL,
+  ipb_range_end tinyblob NOT NULL,
+  ipb_deleted bool NOT NULL default 0,
+  ipb_block_email bool NOT NULL default 0,
+  ipb_allow_usertalk bool NOT NULL default 0,
+  ipb_parent_block_id int default NULL,
+  ipb_sitewide bool NOT NULL default 1
+) /*$wgDBTableOptions*/;
+
+INSERT OR IGNORE INTO /*_*/ipblocks_tmp (
+       ipb_id, ipb_address, ipb_user, ipb_by_actor, ipb_reason_id,
+       ipb_timestamp, ipb_auto, ipb_anon_only, ipb_create_account,
+       ipb_enable_autoblock, ipb_expiry, ipb_range_start, ipb_range_end,
+       ipb_deleted, ipb_block_email, ipb_allow_usertalk, ipb_parent_block_id, ipb_sitewide
+  ) SELECT
+       ipb_id, ipb_address, ipb_user, ipb_by_actor, ipb_reason_id,
+       ipb_timestamp, ipb_auto, ipb_anon_only, ipb_create_account,
+       ipb_enable_autoblock, ipb_expiry, ipb_range_start, ipb_range_end,
+       ipb_deleted, ipb_block_email, ipb_allow_usertalk, ipb_parent_block_id, ipb_sitewide
+  FROM /*_*/ipblocks;
+
+DROP TABLE /*_*/ipblocks;
+ALTER TABLE /*_*/ipblocks_tmp RENAME TO /*_*/ipblocks;
+CREATE UNIQUE INDEX /*i*/ipb_address ON /*_*/ipblocks (ipb_address(255), ipb_user, ipb_auto, ipb_anon_only);
+CREATE INDEX /*i*/ipb_user ON /*_*/ipblocks (ipb_user);
+CREATE INDEX /*i*/ipb_range ON /*_*/ipblocks (ipb_range_start(8), ipb_range_end(8));
+CREATE INDEX /*i*/ipb_timestamp ON /*_*/ipblocks (ipb_timestamp);
+CREATE INDEX /*i*/ipb_expiry ON /*_*/ipblocks (ipb_expiry);
+CREATE INDEX /*i*/ipb_parent_block_id ON /*_*/ipblocks (ipb_parent_block_id);
+
+COMMIT;
diff --git a/maintenance/sqlite/archives/patch-logging-drop-log_user.sql b/maintenance/sqlite/archives/patch-logging-drop-log_user.sql
new file mode 100644 (file)
index 0000000..0f5871a
--- /dev/null
@@ -0,0 +1,41 @@
+--
+-- patch-logging-drop-log_user.sql
+--
+-- T188327. Drop old xx_user and xx_user_text fields, and defaults from xx_actor fields.
+
+BEGIN;
+
+DROP TABLE IF EXISTS /*_*/logging_tmp;
+CREATE TABLE /*_*/logging_tmp (
+  log_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  log_type varbinary(32) NOT NULL default '',
+  log_action varbinary(32) NOT NULL default '',
+  log_timestamp binary(14) NOT NULL default '19700101000000',
+  log_actor bigint unsigned NOT NULL DEFAULT 0,
+  log_namespace int NOT NULL default 0,
+  log_title varchar(255) binary NOT NULL default '',
+  log_page int unsigned NULL,
+  log_comment_id bigint unsigned NOT NULL,
+  log_params blob NOT NULL,
+  log_deleted tinyint unsigned NOT NULL default 0
+) /*$wgDBTableOptions*/;
+
+INSERT OR IGNORE INTO /*_*/logging_tmp (
+       log_id, log_type, log_action, log_timestamp, log_actor,
+       log_namespace, log_title, log_page, log_comment_id, log_params, log_deleted
+  ) SELECT
+       log_id, log_type, log_action, log_timestamp, log_actor,
+       log_namespace, log_title, log_page, log_comment_id, log_params, log_deleted
+  FROM /*_*/logging;
+
+DROP TABLE /*_*/logging;
+ALTER TABLE /*_*/logging_tmp RENAME TO /*_*/logging;
+CREATE INDEX /*i*/type_time ON /*_*/logging (log_type, log_timestamp);
+CREATE INDEX /*i*/actor_time ON /*_*/logging (log_actor, log_timestamp);
+CREATE INDEX /*i*/page_time ON /*_*/logging (log_namespace, log_title, log_timestamp);
+CREATE INDEX /*i*/times ON /*_*/logging (log_timestamp);
+CREATE INDEX /*i*/log_actor_type_time ON /*_*/logging (log_actor, log_type, log_timestamp);
+CREATE INDEX /*i*/log_page_id_time ON /*_*/logging (log_page,log_timestamp);
+CREATE INDEX /*i*/log_type_action ON /*_*/logging (log_type, log_action, log_timestamp);
+
+COMMIT;
diff --git a/maintenance/sqlite/archives/patch-oldimage-drop-oi_user.sql b/maintenance/sqlite/archives/patch-oldimage-drop-oi_user.sql
new file mode 100644 (file)
index 0000000..8735238
--- /dev/null
@@ -0,0 +1,44 @@
+--
+-- patch-oldimage-drop-oi_user.sql
+--
+-- T188327. Drop old xx_user and xx_user_text fields, and defaults from xx_actor fields.
+
+BEGIN;
+
+DROP TABLE IF EXISTS /*_*/oldimage_tmp;
+CREATE TABLE /*_*/oldimage_tmp (
+  oi_name varchar(255) binary NOT NULL default '',
+  oi_archive_name varchar(255) binary NOT NULL default '',
+  oi_size int unsigned NOT NULL default 0,
+  oi_width int NOT NULL default 0,
+  oi_height int NOT NULL default 0,
+  oi_bits int NOT NULL default 0,
+  oi_description_id bigint unsigned NOT NULL,
+  oi_actor bigint unsigned NOT NULL,
+  oi_timestamp binary(14) NOT NULL default '',
+  oi_metadata mediumblob NOT NULL,
+  oi_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE", "3D") default NULL,
+  oi_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical") NOT NULL default "unknown",
+  oi_minor_mime varbinary(100) NOT NULL default "unknown",
+  oi_deleted tinyint unsigned NOT NULL default 0,
+  oi_sha1 varbinary(32) NOT NULL default ''
+) /*$wgDBTableOptions*/;
+
+INSERT OR IGNORE INTO /*_*/oldimage_tmp (
+       oi_name, oi_archive_name, oi_size, oi_width, oi_height, oi_bits,
+       oi_description_id, oi_actor, oi_timestamp, oi_metadata,
+       oi_media_type, oi_major_mime, oi_minor_mime, oi_deleted, oi_sha1
+  ) SELECT
+       oi_name, oi_archive_name, oi_size, oi_width, oi_height, oi_bits,
+       oi_description_id, oi_actor, oi_timestamp, oi_metadata,
+       oi_media_type, oi_major_mime, oi_minor_mime, oi_deleted, oi_sha1
+  FROM /*_*/oldimage;
+
+DROP TABLE /*_*/oldimage;
+ALTER TABLE /*_*/oldimage_tmp RENAME TO /*_*/oldimage;
+CREATE INDEX /*i*/oi_actor_timestamp ON /*_*/oldimage (oi_actor,oi_timestamp);
+CREATE INDEX /*i*/oi_name_timestamp ON /*_*/oldimage (oi_name,oi_timestamp);
+CREATE INDEX /*i*/oi_name_archive_name ON /*_*/oldimage (oi_name,oi_archive_name(14));
+CREATE INDEX /*i*/oi_sha1 ON /*_*/oldimage (oi_sha1(10));
+
+COMMIT;
diff --git a/maintenance/sqlite/archives/patch-recentchanges-drop-rc_user.sql b/maintenance/sqlite/archives/patch-recentchanges-drop-rc_user.sql
new file mode 100644 (file)
index 0000000..ba1f434
--- /dev/null
@@ -0,0 +1,59 @@
+--
+-- patch-recentchanges-drop-rc_user.sql
+--
+-- T188327. Drop old xx_user and xx_user_text fields, and defaults from xx_actor fields.
+
+BEGIN;
+
+DROP TABLE IF EXISTS /*_*/recentchanges_tmp;
+CREATE TABLE /*_*/recentchanges_tmp (
+  rc_id int NOT NULL PRIMARY KEY AUTO_INCREMENT,
+  rc_timestamp varbinary(14) NOT NULL default '',
+  rc_actor bigint unsigned NOT NULL DEFAULT 0,
+  rc_namespace int NOT NULL default 0,
+  rc_title varchar(255) binary NOT NULL default '',
+  rc_comment_id bigint unsigned NOT NULL,
+  rc_minor tinyint unsigned NOT NULL default 0,
+  rc_bot tinyint unsigned NOT NULL default 0,
+  rc_new tinyint unsigned NOT NULL default 0,
+  rc_cur_id int unsigned NOT NULL default 0,
+  rc_this_oldid int unsigned NOT NULL default 0,
+  rc_last_oldid int unsigned NOT NULL default 0,
+  rc_type tinyint unsigned NOT NULL default 0,
+  rc_source varchar(16) binary not null default '',
+  rc_patrolled tinyint unsigned NOT NULL default 0,
+  rc_ip varbinary(40) NOT NULL default '',
+  rc_old_len int,
+  rc_new_len int,
+  rc_deleted tinyint unsigned NOT NULL default 0,
+  rc_logid int unsigned NOT NULL default 0,
+  rc_log_type varbinary(255) NULL default NULL,
+  rc_log_action varbinary(255) NULL default NULL,
+  rc_params blob NULL
+) /*$wgDBTableOptions*/;
+
+INSERT OR IGNORE INTO /*_*/recentchanges_tmp (
+       rc_id, rc_timestamp, rc_actor, rc_namespace, rc_title,
+       rc_comment_id, rc_minor, rc_bot, rc_new, rc_cur_id, rc_this_oldid, rc_last_oldid,
+       rc_type, rc_source, rc_patrolled, rc_ip, rc_old_len, rc_new_len, rc_deleted,
+       rc_logid, rc_log_type, rc_log_action, rc_params
+  ) SELECT
+       rc_id, rc_timestamp, rc_actor, rc_namespace, rc_title,
+       rc_comment_id, rc_minor, rc_bot, rc_new, rc_cur_id, rc_this_oldid, rc_last_oldid,
+       rc_type, rc_source, rc_patrolled, rc_ip, rc_old_len, rc_new_len, rc_deleted,
+       rc_logid, rc_log_type, rc_log_action, rc_params
+  FROM /*_*/recentchanges;
+
+DROP TABLE /*_*/recentchanges;
+ALTER TABLE /*_*/recentchanges_tmp RENAME TO /*_*/recentchanges;
+CREATE INDEX /*i*/rc_timestamp ON /*_*/recentchanges (rc_timestamp);
+CREATE INDEX /*i*/rc_namespace_title_timestamp ON /*_*/recentchanges (rc_namespace, rc_title, rc_timestamp);
+CREATE INDEX /*i*/rc_cur_id ON /*_*/recentchanges (rc_cur_id);
+CREATE INDEX /*i*/new_name_timestamp ON /*_*/recentchanges (rc_new,rc_namespace,rc_timestamp);
+CREATE INDEX /*i*/rc_ip ON /*_*/recentchanges (rc_ip);
+CREATE INDEX /*i*/rc_ns_actor ON /*_*/recentchanges (rc_namespace, rc_actor);
+CREATE INDEX /*i*/rc_actor ON /*_*/recentchanges (rc_actor, rc_timestamp);
+CREATE INDEX /*i*/rc_name_type_patrolled_timestamp ON /*_*/recentchanges (rc_namespace, rc_type, rc_patrolled, rc_timestamp);
+CREATE INDEX /*i*/rc_this_oldid ON /*_*/recentchanges (rc_this_oldid);
+
+COMMIT;
index 979e68a..e3c6c02 100644 (file)
@@ -1,6 +1,6 @@
 -- Blobs table for external storage
 
-CREATE TABLE /*$wgDBprefix*/blobs (
+CREATE TABLE IF NOT EXISTS /*$wgDBprefix*/blobs (
        blob_id integer UNSIGNED NOT NULL AUTO_INCREMENT,
        blob_text longblob,
        PRIMARY KEY  (blob_id)
index 060f327..37625cf 100644 (file)
@@ -232,7 +232,7 @@ class CheckStorage {
                                }
                                foreach ( $externalConcatBlobs as $cluster => $xBlobIds ) {
                                        $blobIds = array_keys( $xBlobIds );
-                                       $extDb =& $this->dbStore->getSlave( $cluster );
+                                       $extDb =& $this->dbStore->getReplica( $cluster );
                                        $blobsTable = $this->dbStore->getTable( $extDb );
                                        $res = $extDb->select( $blobsTable,
                                                [ 'blob_id' ],
@@ -433,7 +433,7 @@ class CheckStorage {
 
                foreach ( $externalConcatBlobs as $cluster => $oldIds ) {
                        $blobIds = array_keys( $oldIds );
-                       $extDb =& $this->dbStore->getSlave( $cluster );
+                       $extDb =& $this->dbStore->getReplica( $cluster );
                        $blobsTable = $this->dbStore->getTable( $extDb );
                        $headerLength = strlen( self::CONCAT_HEADER );
                        $res = $extDb->select( $blobsTable,
index 0d506ef..9f20e67 100644 (file)
@@ -713,6 +713,8 @@ class CgzCopyTransaction {
        /** @var ConcatenatedGzipHistoryBlob|false */
        public $cgz;
        public $referrers;
+       /** @var array */
+       private $texts;
 
        /**
         * Create a transaction from a RecompressTracked object
index df15abf..55c6775 100644 (file)
@@ -594,9 +594,7 @@ CREATE TABLE /*_*/archive (
 
   -- Basic revision stuff...
   ar_comment_id bigint unsigned NOT NULL,
-  ar_user int unsigned NOT NULL default 0, -- Deprecated in favor of ar_actor
-  ar_user_text varchar(255) binary NOT NULL DEFAULT '', -- Deprecated in favor of ar_actor
-  ar_actor bigint unsigned NOT NULL DEFAULT 0, -- ("DEFAULT 0" is temporary, signaling that ar_user/ar_user_text should be used)
+  ar_actor bigint unsigned NOT NULL,
   ar_timestamp binary(14) NOT NULL default '',
   ar_minor_edit tinyint NOT NULL default 0,
 
@@ -661,7 +659,6 @@ CREATE TABLE /*_*/archive (
 CREATE INDEX /*i*/name_title_timestamp ON /*_*/archive (ar_namespace,ar_title,ar_timestamp);
 
 -- Index for Special:DeletedContributions
-CREATE INDEX /*i*/ar_usertext_timestamp ON /*_*/archive (ar_user_text,ar_timestamp);
 CREATE INDEX /*i*/ar_actor_timestamp ON /*_*/archive (ar_actor,ar_timestamp);
 
 -- Index for linking archive rows with tables that normally link with revision
@@ -1034,14 +1031,8 @@ CREATE TABLE /*_*/ipblocks (
   -- Blocked user ID or 0 for IP blocks.
   ipb_user int unsigned NOT NULL default 0,
 
-  -- User ID who made the block.
-  ipb_by int unsigned NOT NULL default 0, -- Deprecated in favor of ipb_by_actor
-
-  -- User name of blocker
-  ipb_by_text varchar(255) binary NOT NULL default '', -- Deprecated in favor of ipb_by_actor
-
   -- Actor who made the block.
-  ipb_by_actor bigint unsigned NOT NULL DEFAULT 0, -- ("DEFAULT 0" is temporary, signaling that ipb_by/ipb_by_text should be used)
+  ipb_by_actor bigint unsigned NOT NULL,
 
   -- Key to comment_id. Text comment made by blocker.
   ipb_reason_id bigint unsigned NOT NULL,
@@ -1177,14 +1168,8 @@ CREATE TABLE /*_*/image (
   -- This is displayed in image upload history and logs.
   img_description_id bigint unsigned NOT NULL,
 
-  -- user_id and user_name of uploader.
-  -- Deprecated in favor of img_actor.
-  img_user int unsigned NOT NULL default 0,
-  img_user_text varchar(255) binary NOT NULL DEFAULT '',
-
   -- actor_id of the uploader.
-  -- ("DEFAULT 0" is temporary, signaling that img_user/img_user_text should be used)
-  img_actor bigint unsigned NOT NULL DEFAULT 0,
+  img_actor bigint unsigned NOT NULL,
 
   -- Time of the upload.
   img_timestamp varbinary(14) NOT NULL default '',
@@ -1194,8 +1179,6 @@ CREATE TABLE /*_*/image (
 ) /*$wgDBTableOptions*/;
 
 -- Used by Special:Newimages and ApiQueryAllImages
-CREATE INDEX /*i*/img_user_timestamp ON /*_*/image (img_user,img_timestamp);
-CREATE INDEX /*i*/img_usertext_timestamp ON /*_*/image (img_user_text,img_timestamp);
 CREATE INDEX /*i*/img_actor_timestamp ON /*_*/image (img_actor,img_timestamp);
 -- Used by Special:ListFiles for sort-by-size
 CREATE INDEX /*i*/img_size ON /*_*/image (img_size);
@@ -1226,9 +1209,7 @@ CREATE TABLE /*_*/oldimage (
   oi_height int NOT NULL default 0,
   oi_bits int NOT NULL default 0,
   oi_description_id bigint unsigned NOT NULL,
-  oi_user int unsigned NOT NULL default 0, -- Deprecated in favor of oi_actor
-  oi_user_text varchar(255) binary NOT NULL DEFAULT '', -- Deprecated in favor of oi_actor
-  oi_actor bigint unsigned NOT NULL DEFAULT 0, -- ("DEFAULT 0" is temporary, signaling that oi_user/oi_user_text should be used)
+  oi_actor bigint unsigned NOT NULL,
   oi_timestamp binary(14) NOT NULL default '',
 
   oi_metadata mediumblob NOT NULL,
@@ -1239,7 +1220,6 @@ CREATE TABLE /*_*/oldimage (
   oi_sha1 varbinary(32) NOT NULL default ''
 ) /*$wgDBTableOptions*/;
 
-CREATE INDEX /*i*/oi_usertext_timestamp ON /*_*/oldimage (oi_user_text,oi_timestamp);
 CREATE INDEX /*i*/oi_actor_timestamp ON /*_*/oldimage (oi_actor,oi_timestamp);
 CREATE INDEX /*i*/oi_name_timestamp ON /*_*/oldimage (oi_name,oi_timestamp);
 -- oi_archive_name truncated to 14 to avoid key length overflow
@@ -1287,9 +1267,7 @@ CREATE TABLE /*_*/filearchive (
   fa_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart", "chemical") default "unknown",
   fa_minor_mime varbinary(100) default "unknown",
   fa_description_id bigint unsigned NOT NULL,
-  fa_user int unsigned default 0, -- Deprecated in favor of fa_actor
-  fa_user_text varchar(255) binary DEFAULT '', -- Deprecated in favor of fa_actor
-  fa_actor bigint unsigned NOT NULL DEFAULT 0, -- ("DEFAULT 0" is temporary, signaling that fa_user/fa_user_text should be used)
+  fa_actor bigint unsigned NOT NULL,
   fa_timestamp binary(14) default '',
 
   -- Visibility of deleted revisions, bitfield
@@ -1306,7 +1284,6 @@ CREATE INDEX /*i*/fa_storage_group ON /*_*/filearchive (fa_storage_group, fa_sto
 -- sort by deletion time
 CREATE INDEX /*i*/fa_deleted_timestamp ON /*_*/filearchive (fa_deleted_timestamp);
 -- sort by uploader
-CREATE INDEX /*i*/fa_user_timestamp ON /*_*/filearchive (fa_user_text,fa_timestamp);
 CREATE INDEX /*i*/fa_actor_timestamp ON /*_*/filearchive (fa_actor,fa_timestamp);
 -- find file by sha1, 10 bytes will be enough for hashes to be indexed
 CREATE INDEX /*i*/fa_sha1 ON /*_*/filearchive (fa_sha1(10));
@@ -1378,9 +1355,7 @@ CREATE TABLE /*_*/recentchanges (
   rc_timestamp varbinary(14) NOT NULL default '',
 
   -- As in revision
-  rc_user int unsigned NOT NULL default 0, -- Deprecated in favor of rc_actor
-  rc_user_text varchar(255) binary NOT NULL DEFAULT '', -- Deprecated in favor of rc_actor
-  rc_actor bigint unsigned NOT NULL DEFAULT 0, -- ("DEFAULT 0" is temporary, signaling that rc_user/rc_user_text should be used)
+  rc_actor bigint unsigned NOT NULL,
 
   -- When pages are renamed, their RC entries do _not_ change.
   rc_namespace int NOT NULL default 0,
@@ -1461,11 +1436,9 @@ CREATE INDEX /*i*/new_name_timestamp ON /*_*/recentchanges (rc_new,rc_namespace,
 CREATE INDEX /*i*/rc_ip ON /*_*/recentchanges (rc_ip);
 
 -- Probably intended for Special:NewPages namespace filter
-CREATE INDEX /*i*/rc_ns_usertext ON /*_*/recentchanges (rc_namespace, rc_user_text);
 CREATE INDEX /*i*/rc_ns_actor ON /*_*/recentchanges (rc_namespace, rc_actor);
 
 -- SiteStats active user count, Special:ActiveUsers, Special:NewPages user filter
-CREATE INDEX /*i*/rc_user_text ON /*_*/recentchanges (rc_user_text, rc_timestamp);
 CREATE INDEX /*i*/rc_actor ON /*_*/recentchanges (rc_actor, rc_timestamp);
 
 -- ApiQueryRecentChanges (T140108)
@@ -1595,14 +1568,8 @@ CREATE TABLE /*_*/logging (
   -- Timestamp. Duh.
   log_timestamp binary(14) NOT NULL default '19700101000000',
 
-  -- The user who performed this action; key to user_id
-  log_user int unsigned NOT NULL default 0, -- Deprecated in favor of log_actor
-
-  -- Name of the user who performed this action
-  log_user_text varchar(255) binary NOT NULL default '', -- Deprecated in favor of log_actor
-
   -- The actor who performed this action
-  log_actor bigint unsigned NOT NULL DEFAULT 0, -- ("DEFAULT 0" is temporary, signaling that log_user/log_user_text should be used)
+  log_actor bigint unsigned NOT NULL,
 
   -- Key to the page affected. Where a user is the target,
   -- this will point to the user page.
@@ -1625,7 +1592,6 @@ CREATE TABLE /*_*/logging (
 CREATE INDEX /*i*/type_time ON /*_*/logging (log_type, log_timestamp);
 
 -- Special:Log performer filter
-CREATE INDEX /*i*/user_time ON /*_*/logging (log_user, log_timestamp);
 CREATE INDEX /*i*/actor_time ON /*_*/logging (log_actor, log_timestamp);
 
 -- Special:Log title filter, log extract
@@ -1635,7 +1601,6 @@ CREATE INDEX /*i*/page_time ON /*_*/logging (log_namespace, log_title, log_times
 CREATE INDEX /*i*/times ON /*_*/logging (log_timestamp);
 
 -- Special:Log filter by performer and type
-CREATE INDEX /*i*/log_user_type_time ON /*_*/logging (log_user, log_type, log_timestamp);
 CREATE INDEX /*i*/log_actor_type_time ON /*_*/logging (log_actor, log_type, log_timestamp);
 
 -- Apparently just used for a few maintenance pages (findMissingFiles.php, Flow).
@@ -1645,12 +1610,6 @@ CREATE INDEX /*i*/log_page_id_time ON /*_*/logging (log_page,log_timestamp);
 -- Special:Log action filter
 CREATE INDEX /*i*/log_type_action ON /*_*/logging (log_type, log_action, log_timestamp);
 
--- Special:Log filter by type and anonymous performer
-CREATE INDEX /*i*/log_user_text_type_time ON /*_*/logging (log_user_text, log_type, log_timestamp);
-
--- Special:Log filter by anonymous performer
-CREATE INDEX /*i*/log_user_text_time ON /*_*/logging (log_user_text, log_timestamp);
-
 
 CREATE TABLE /*_*/log_search (
   -- The type of ID (rev ID, log ID, rev timestamp, username)
index 98f1c24..2f8941f 100644 (file)
@@ -110,11 +110,10 @@ The new option is NOT validated.' );
                                        $ret[$option][$userValue] = ( $ret[$option][$userValue] ?? 0 ) + 1;
                                }
                        } else {
-
                                foreach ( $defaultOptions as $name => $defaultValue ) {
                                        $userValue = $user->getOption( $name );
                                        if ( $userValue != $defaultValue ) {
-                                               $ret[$option][$userValue] = ( $ret[$option][$userValue] ?? 0 ) + 1;
+                                               $ret[$name][$userValue] = ( $ret[$name][$userValue] ?? 0 ) + 1;
                                        }
                                }
                        }
index b546cbf..6425238 100644 (file)
@@ -24,6 +24,8 @@
 // details of the session. Enforce this constraint with respect to session use.
 define( 'MW_NO_SESSION', 1 );
 
+define( 'MW_ENTRY_POINT', 'opensearch_desc' );
+
 require_once __DIR__ . '/includes/WebStart.php';
 
 if ( $wgRequest->getVal( 'ctype' ) == 'application/xml' ) {
index dccdd38..7b652b7 100644 (file)
@@ -40,6 +40,8 @@
 // details of the session. Enforce this constraint with respect to session use.
 define( 'MW_NO_SESSION', 1 );
 
+define( 'MW_ENTRY_POINT', 'profileinfo' );
+
 ini_set( 'zlib.output_compression', 'off' );
 
 require __DIR__ . '/includes/WebStart.php';
index b3aee84..180ed65 100644 (file)
@@ -175,11 +175,10 @@ return [
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'jquery.color' => [
-               'scripts' => 'resources/src/jquery/jquery.color.js',
-               'dependencies' => 'jquery.colorUtil',
-       ],
-       'jquery.colorUtil' => [
-               'scripts' => 'resources/src/jquery/jquery.colorUtil.js',
+               'scripts' => [
+                       'resources/src/jquery.color/jquery.colorUtil.js',
+                       'resources/src/jquery.color/jquery.color.js',
+               ],
        ],
        'jquery.confirmable' => [
                'scripts' => [
@@ -895,6 +894,7 @@ return [
                'dependencies' => [
                        'mediawiki.api',
                        'oojs',
+                       'mediawiki.Uri',
                ],
                'targets' => [ 'desktop', 'mobile' ],
        ],
@@ -940,6 +940,9 @@ return [
                'scripts' => [
                        'resources/src/mediawiki.htmlform.checker.js',
                ],
+               'dependencies' => [
+                       'mediawiki.util',
+               ],
                'targets' => [ 'desktop', 'mobile' ],
        ],
        'mediawiki.htmlform.ooui' => [
@@ -1028,7 +1031,6 @@ return [
        ],
        'mediawiki.RegExp' => [
                'deprecated' => 'Please use mw.util.escapeRegExp() instead.',
-               'scripts' => 'resources/src/mediawiki.RegExp.js',
                'targets' => [ 'desktop', 'mobile' ],
                'dependencies' => [
                        'mediawiki.util',
@@ -1253,8 +1255,8 @@ return [
                ]
        ],
        'mediawiki.util' => [
-               'localBasePath' => "$IP/resources/src/mediawiki.util/",
-               'remoteBasePath' => "$wgResourceBasePath/resources/src/mediawiki.util/",
+               'localBasePath' => "$IP/resources/src/mediawiki.util",
+               'remoteBasePath' => "$wgResourceBasePath/resources/src/mediawiki.util",
                'packageFiles' => [
                        'util.js',
                        'jquery.accessKeyLabel.js',
@@ -1702,7 +1704,6 @@ return [
                        'mediawiki.util',
                        'mediawiki.Title',
                        'mediawiki.jqueryMsg',
-                       'mediawiki.util',
                ],
                'messages' => [
                        'watch',
@@ -2315,7 +2316,6 @@ return [
                'dependencies' => [
                        'mediawiki.api',
                        'mediawiki.jqueryMsg',
-                       'jquery.throttle-debounce',
                        'mediawiki.htmlform.checker',
                ],
        ],
index 9ab1b49..5db52a4 100644 (file)
@@ -253,8 +253,8 @@ oojs-router:
 
 ooui:
   type: tar
-  src: https://registry.npmjs.org/oojs-ui/-/oojs-ui-0.34.0.tgz
-  integrity: sha384-DVG3XayKF02r0rqXSJUEWJImcK8XJeiIVC/Ii5R20cINYpTaAs+x4rdCU52VaKKw
+  src: https://registry.npmjs.org/oojs-ui/-/oojs-ui-0.34.1.tgz
+  integrity: sha384-QXYp5vK60xpu4nkv/JStszI6U4TYGCNe7uXb5rYb7FYURLTR41mtNO74gl7HXgpz
 
   dest:
     # Main stuff
index 9408e9b..501b768 100644 (file)
@@ -1,4 +1,16 @@
 # OOUI Release History
+## v0.34.1 / 2019-09-10
+### Deprecating changes
+* [DEPRECATING CHANGE] icons: Rename 'beaker' to 'labFlask' (Volker E.)
+
+### Styles
+* icons: Add 'userGroup' (Volker E.)
+
+### Code
+* Wrap long strings in popups (Sam Wilson)
+* demos: Add missing file to PHP demo to fix infusion (Bartosz Dziewoński)
+
+
 ## v0.34.0 / 2019-09-04
 ### Breaking changes
 * [BREAKING CHANGE] Use OOjs v3.0.0, up from v2.2.2 (James D. Forrester)
index 6bfe4d6..8595f61 100644 (file)
        "ooui-item-remove": "Supprimer",
        "ooui-dialog-message-accept": "OK",
        "ooui-dialog-message-reject": "Annuler",
-       "ooui-dialog-process-error": "Quelque chose s'est mal passé",
+       "ooui-dialog-process-error": "Quelque chose sest mal passé",
        "ooui-dialog-process-dismiss": "Fermer",
        "ooui-dialog-process-retry": "Réessayer",
        "ooui-dialog-process-continue": "Continuer",
-       "ooui-combobox-button-label": "Liste déroulante de combobox",
+       "ooui-combobox-button-label": "Liste déroulante pour boîte de saisie",
        "ooui-selectfile-button-select": "Sélectionner un fichier",
        "ooui-selectfile-not-supported": "La sélection de fichier n’est pas prise en charge",
        "ooui-selectfile-placeholder": "Aucun fichier sélectionné",
index affc066..d13cb45 100644 (file)
@@ -18,7 +18,8 @@
                        "Gloria sah",
                        "Andrzej aa",
                        "The Polish",
-                       "Railfail536"
+                       "Railfail536",
+                       "Rail"
                ]
        },
        "ooui-outline-control-move-down": "Przesuń w dół",
index d48a492..667f11e 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index bb58190..e06ece0 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-element-hidden {
   display: none !important;
@@ -917,6 +917,8 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
 .oo-ui-popupWidget-popup {
   position: relative;
   overflow: hidden;
+  word-wrap: break-word;
+  overflow-wrap: break-word;
 }
 .oo-ui-popupWidget-anchor {
   display: none;
index cfbf7d6..d4eaea5 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-element-hidden {
   display: none !important;
@@ -1059,6 +1059,8 @@ body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
 .oo-ui-popupWidget-popup {
   position: relative;
   overflow: hidden;
+  word-wrap: break-word;
+  overflow-wrap: break-word;
 }
 .oo-ui-popupWidget-anchor {
   display: none;
index 11e132e..9754fb8 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index fda6a81..768d107 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-tool > .oo-ui-tool-link > .oo-ui-tool-checkIcon {
   display: none;
index c011942..5e8b9c9 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-tool {
   -webkit-box-sizing: border-box;
index 000b9eb..e8a571e 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index 854d8e3..f94e98b 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-draggableElement-handle:not( .oo-ui-draggableElement-undraggable ).oo-ui-widget {
   cursor: move;
index 73da6f8..8bc82a8 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 .oo-ui-draggableElement-handle:not( .oo-ui-draggableElement-undraggable ).oo-ui-widget {
   cursor: move;
index bdf0d2f..7afac69 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index 75f1acd..5355835 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index 8ac442f..5a11914 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 
 .oo-ui-window {
index e406188..b1a067b 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:59Z
+ * Date: 2019-09-10T23:46:11Z
  */
 
 .oo-ui-window {
index 8885525..d8db8d1 100644 (file)
@@ -1,12 +1,12 @@
 /*!
- * OOUI v0.34.0-pre (d5e74518ab)
+ * OOUI v0.34.1-pre (3913589098)
  * https://www.mediawiki.org/wiki/OOUI
  *
  * Copyright 2011–2019 OOUI Team and other contributors.
  * Released under the MIT license
  * http://oojs.mit-license.org
  *
- * Date: 2019-09-04T18:28:52Z
+ * Date: 2019-09-10T23:46:03Z
  */
 ( function ( OO ) {
 
index 732d70f..516dc08 100644 (file)
@@ -15,7 +15,8 @@
                        "file": "../wikimediaui/images/icons/attachment.svg"
                },
                "beaker": {
-                       "file": "../wikimediaui/images/icons/beaker.svg"
+                       "file": "../wikimediaui/images/icons/labFlask.svg",
+                       "deprecated": "Renamed since v0.34.1, use 'labFlask' instead."
                },
                "calendar": {
                        "file": "../wikimediaui/images/icons/calendar.svg"
@@ -38,6 +39,9 @@
                "imageLayoutThumbnail": {
                        "file": "../wikimediaui/images/icons/imageLayoutThumbnail.svg"
                },
+               "labFlask": {
+                       "file": "../wikimediaui/images/icons/labFlask.svg"
+               },
                "language": {
                        "file": "../wikimediaui/images/icons/language.svg"
                },
index e13bb1d..de7a118 100644 (file)
                "userAvatarOutline": {
                        "file": "../wikimediaui/images/icons/userAvatarOutline.svg"
                },
+               "userGroup": {
+                       "file": {
+                               "ltr": "../wikimediaui/images/icons/userGroup-ltr.svg",
+                               "rtl": "../wikimediaui/images/icons/userGroup-rtl.svg"
+                       }
+               },
                "userTalk": {
                        "file": {
                                "ltr": "../wikimediaui/images/icons/userTalk-ltr.svg",
index 4f4fd4e..23dd607 100644 (file)
@@ -38,7 +38,8 @@
                        "file": "images/icons/attachment.svg"
                },
                "beaker": {
-                       "file": "images/icons/beaker.svg"
+                       "file": "images/icons/labFlask.svg",
+                       "deprecated": "Renamed since v0.34.1, use 'labFlask' instead."
                },
                "calendar": {
                        "file": "images/icons/calendar.svg"
@@ -61,6 +62,9 @@
                "imageLayoutThumbnail": {
                        "file": "images/icons/imageLayoutThumbnail.svg"
                },
+               "labFlask": {
+                       "file": "images/icons/labFlask.svg"
+               },
                "language": {
                        "file": "images/icons/language.svg"
                },
index 7266d34..5a382ce 100644 (file)
                "userAvatarOutline": {
                        "file": "images/icons/userAvatarOutline.svg"
                },
+               "userGroup": {
+                       "file": {
+                               "ltr": "images/icons/userGroup-ltr.svg",
+                               "rtl": "images/icons/userGroup-rtl.svg"
+                       }
+               },
                "userTalk": {
                        "file": {
                                "ltr": "images/icons/userTalk-ltr.svg",
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.png b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.png
deleted file mode 100644 (file)
index 89d2d3d..0000000
Binary files a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.png and /dev/null differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-invert.svg
deleted file mode 100644 (file)
index c031daf..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
-       <title>
-               beaker
-       </title><g fill="#fff">
-       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
-</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.png b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.png
deleted file mode 100644 (file)
index 78736ac..0000000
Binary files a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.png and /dev/null differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker-progressive.svg
deleted file mode 100644 (file)
index 1f8efbd..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
-       <title>
-               beaker
-       </title><g fill="#36c">
-       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
-</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.png b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.png
deleted file mode 100644 (file)
index 63a1a80..0000000
Binary files a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.png and /dev/null differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/beaker.svg
deleted file mode 100644 (file)
index 7a37c5a..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
-       <title>
-               beaker
-       </title>
-       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
-</svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.png b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.png
new file mode 100644 (file)
index 0000000..89d2d3d
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-invert.svg
new file mode 100644 (file)
index 0000000..bfb66da
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               laboratory flask
+       </title><g fill="#fff">
+       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.png b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.png
new file mode 100644 (file)
index 0000000..78736ac
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask-progressive.svg
new file mode 100644 (file)
index 0000000..1db0d6b
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               laboratory flask
+       </title><g fill="#36c">
+       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.png b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.png
new file mode 100644 (file)
index 0000000..63a1a80
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/labFlask.svg
new file mode 100644 (file)
index 0000000..c95a51a
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               laboratory flask
+       </title>
+       <path d="M13 7.61V3h1V1H6v2h1v4.61l-5.86 9.88A1 1 0 0 0 2 19h16a1 1 0 0 0 .86-1.51zm-4.2.88a1 1 0 0 0 .2-.6V3h2v4.89a1 1 0 0 0 .14.51l2.14 3.6H6.72z"/>
+</svg>
index 3b5187d..268dc30 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
        <title>
                user avatar
index 047a18c..681a468 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
        <title>
                user avatar
index 7608cd2..8236235 100644 (file)
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="UTF-8"?>
 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
        <title>
                user avatar
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.png
new file mode 100644 (file)
index 0000000..bc9c111
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-invert.svg
new file mode 100644 (file)
index 0000000..d05ad38
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title><g fill="#fff">
+       <path d="M14 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zM6 3c1.66 0 3 1.34 3 3S7.66 9 6 9 3 7.66 3 6s1.34-3 3-3zm8 7c3.31 0 6 1.79 6 4v2h-6v-2c0-1.48-1.21-2.77-3-3.46.88-.35 1.91-.54 3-.54zm-8 0c3.31 0 6 1.79 6 4v2H0v-2c0-2.21 2.69-4 6-4z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.png
new file mode 100644 (file)
index 0000000..5cd3d1c
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr-progressive.svg
new file mode 100644 (file)
index 0000000..71d354a
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title><g fill="#36c">
+       <path d="M14 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zM6 3c1.66 0 3 1.34 3 3S7.66 9 6 9 3 7.66 3 6s1.34-3 3-3zm8 7c3.31 0 6 1.79 6 4v2h-6v-2c0-1.48-1.21-2.77-3-3.46.88-.35 1.91-.54 3-.54zm-8 0c3.31 0 6 1.79 6 4v2H0v-2c0-2.21 2.69-4 6-4z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.png
new file mode 100644 (file)
index 0000000..43c0be2
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-ltr.svg
new file mode 100644 (file)
index 0000000..248d056
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title>
+       <path d="M14 3c1.66 0 3 1.34 3 3s-1.34 3-3 3-3-1.34-3-3 1.34-3 3-3zM6 3c1.66 0 3 1.34 3 3S7.66 9 6 9 3 7.66 3 6s1.34-3 3-3zm8 7c3.31 0 6 1.79 6 4v2h-6v-2c0-1.48-1.21-2.77-3-3.46.88-.35 1.91-.54 3-.54zm-8 0c3.31 0 6 1.79 6 4v2H0v-2c0-2.21 2.69-4 6-4z"/>
+</svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.png
new file mode 100644 (file)
index 0000000..2147e81
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-invert.svg
new file mode 100644 (file)
index 0000000..5604358
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title><g fill="#fff">
+       <path d="M6 3C4.34 3 3 4.34 3 6s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm8 0c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm-8 7c-3.31 0-6 1.79-6 4v2h6v-2c0-1.48 1.21-2.77 3-3.46-.88-.35-1.91-.54-3-.54zm8 0c-3.31 0-6 1.79-6 4v2h12v-2c0-2.21-2.69-4-6-4z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.png
new file mode 100644 (file)
index 0000000..d9082d3
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl-progressive.svg
new file mode 100644 (file)
index 0000000..75436e9
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title><g fill="#36c">
+       <path d="M6 3C4.34 3 3 4.34 3 6s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm8 0c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm-8 7c-3.31 0-6 1.79-6 4v2h6v-2c0-1.48 1.21-2.77 3-3.46-.88-.35-1.91-.54-3-.54zm8 0c-3.31 0-6 1.79-6 4v2h12v-2c0-2.21-2.69-4-6-4z"/>
+</g></svg>
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.png b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.png
new file mode 100644 (file)
index 0000000..4eedd2e
Binary files /dev/null and b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.png differ
diff --git a/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.svg b/resources/lib/ooui/themes/wikimediaui/images/icons/userGroup-rtl.svg
new file mode 100644 (file)
index 0000000..5bd5bf5
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+       <title>
+               user group
+       </title>
+       <path d="M6 3C4.34 3 3 4.34 3 6s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm8 0c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3zm-8 7c-3.31 0-6 1.79-6 4v2h6v-2c0-1.48 1.21-2.77 3-3.46-.88-.35-1.91-.54-3-.54zm8 0c-3.31 0-6 1.79-6 4v2h12v-2c0-2.21-2.69-4-6-4z"/>
+</svg>
diff --git a/resources/src/jquery.color/jquery.color.js b/resources/src/jquery.color/jquery.color.js
new file mode 100644 (file)
index 0000000..6df02ad
--- /dev/null
@@ -0,0 +1,55 @@
+/**
+ * jQuery Color Animations
+ *
+ * @author John Resig, 2007
+ * @author Krinkle, 2011
+ * Released under the MIT and GPL licenses.
+ *
+ * - 2011-01-05: Forked for MediaWiki. See also jQuery.colorUtil plugin
+ */
+( function () {
+
+       function getColor( elem, attr ) {
+               var color;
+
+               do {
+                       color = $.css( elem, attr );
+
+                       // Keep going until we find an element that has color, or we hit the body
+                       if ( color !== '' && color !== 'transparent' || elem.nodeName.toLowerCase() === 'body' ) {
+                               break;
+                       }
+
+                       attr = 'backgroundColor';
+               // eslint-disable-next-line no-cond-assign
+               } while ( elem = elem.parentNode );
+
+               return $.colorUtil.getRGB( color );
+       }
+
+       // We override the animation for all of these color styles
+       [
+               'backgroundColor',
+               'borderBottomColor',
+               'borderLeftColor',
+               'borderRightColor',
+               'borderTopColor',
+               'color',
+               'outlineColor'
+       ].forEach( function ( attr ) {
+               $.fx.step[ attr ] = function ( fx ) {
+                       if ( !fx.colorInit ) {
+                               fx.start = getColor( fx.elem, attr );
+                               fx.end = $.colorUtil.getRGB( fx.end );
+                               fx.colorInit = true;
+                       }
+
+                       fx.elem.style[ attr ] = 'rgb(' + [
+                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 0 ] - fx.start[ 0 ] ) ) + fx.start[ 0 ], 10 ), 255 ), 0 ),
+                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 1 ] - fx.start[ 1 ] ) ) + fx.start[ 1 ], 10 ), 255 ), 0 ),
+                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 2 ] - fx.start[ 2 ] ) ) + fx.start[ 2 ], 10 ), 255 ), 0 )
+                       ].join( ',' ) + ')';
+               };
+       } );
+
+}() );
diff --git a/resources/src/jquery.color/jquery.colorUtil.js b/resources/src/jquery.color/jquery.colorUtil.js
new file mode 100644 (file)
index 0000000..009be1a
--- /dev/null
@@ -0,0 +1,268 @@
+/*!
+ * jQuery Color Utilities
+ *
+ * Released under the MIT and GPL licenses.
+ *
+ * Mostly based on other plugins and functions (linted and optimized a little).
+ * Sources cited inline.
+ */
+( function () {
+       /**
+        * @class jQuery.colorUtil
+        * @singleton
+        */
+       $.colorUtil = {
+
+               /**
+                * Parse CSS color strings looking for color tuples
+                *
+                * Based on highlightFade by Blair Mitchelmore
+                * <http://jquery.offput.ca/highlightFade/>
+                *
+                * @param {Array|string} color
+                * @return {Array}
+                */
+               getRGB: function ( color ) {
+                       var result;
+
+                       // Check if we're already dealing with an array of colors
+                       if ( color && Array.isArray( color ) && color.length === 3 ) {
+                               return color;
+                       }
+                       if ( typeof color !== 'string' ) {
+                               return undefined;
+                       }
+
+                       // Look for rgb(num,num,num)
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec( color ) ) {
+                               return [
+                                       parseInt( result[ 1 ], 10 ),
+                                       parseInt( result[ 2 ], 10 ),
+                                       parseInt( result[ 3 ], 10 )
+                               ];
+                       }
+
+                       // Look for rgb(num%,num%,num%)
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*\)/.exec( color ) ) {
+                               return [
+                                       parseFloat( result[ 1 ] ) * 2.55,
+                                       parseFloat( result[ 2 ] ) * 2.55,
+                                       parseFloat( result[ 3 ] ) * 2.55
+                               ];
+                       }
+
+                       // Look for #a0b1c2
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec( color ) ) {
+                               return [
+                                       parseInt( result[ 1 ], 16 ),
+                                       parseInt( result[ 2 ], 16 ),
+                                       parseInt( result[ 3 ], 16 )
+                               ];
+                       }
+
+                       // Look for #fff
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec( color ) ) {
+                               return [
+                                       parseInt( result[ 1 ] + result[ 1 ], 16 ),
+                                       parseInt( result[ 2 ] + result[ 2 ], 16 ),
+                                       parseInt( result[ 3 ] + result[ 3 ], 16 )
+                               ];
+                       }
+
+                       // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
+                       // eslint-disable-next-line no-cond-assign
+                       if ( result = /rgba\(0, 0, 0, 0\)/.exec( color ) ) {
+                               return $.colorUtil.colors.transparent;
+                       }
+
+                       // Otherwise, we're most likely dealing with a named color
+                       return $.colorUtil.colors[ color.trim().toLowerCase() ];
+               },
+
+               /**
+                * Named color map
+                *
+                * Based on Interface by Stefan Petre
+                * <http://interface.eyecon.ro/>
+                *
+                * @property {Object}
+                */
+               colors: {
+                       aqua: [ 0, 255, 255 ],
+                       azure: [ 240, 255, 255 ],
+                       beige: [ 245, 245, 220 ],
+                       black: [ 0, 0, 0 ],
+                       blue: [ 0, 0, 255 ],
+                       brown: [ 165, 42, 42 ],
+                       cyan: [ 0, 255, 255 ],
+                       darkblue: [ 0, 0, 139 ],
+                       darkcyan: [ 0, 139, 139 ],
+                       darkgrey: [ 169, 169, 169 ],
+                       darkgreen: [ 0, 100, 0 ],
+                       darkkhaki: [ 189, 183, 107 ],
+                       darkmagenta: [ 139, 0, 139 ],
+                       darkolivegreen: [ 85, 107, 47 ],
+                       darkorange: [ 255, 140, 0 ],
+                       darkorchid: [ 153, 50, 204 ],
+                       darkred: [ 139, 0, 0 ],
+                       darksalmon: [ 233, 150, 122 ],
+                       darkviolet: [ 148, 0, 211 ],
+                       fuchsia: [ 255, 0, 255 ],
+                       gold: [ 255, 215, 0 ],
+                       green: [ 0, 128, 0 ],
+                       indigo: [ 75, 0, 130 ],
+                       khaki: [ 240, 230, 140 ],
+                       lightblue: [ 173, 216, 230 ],
+                       lightcyan: [ 224, 255, 255 ],
+                       lightgreen: [ 144, 238, 144 ],
+                       lightgrey: [ 211, 211, 211 ],
+                       lightpink: [ 255, 182, 193 ],
+                       lightyellow: [ 255, 255, 224 ],
+                       lime: [ 0, 255, 0 ],
+                       magenta: [ 255, 0, 255 ],
+                       maroon: [ 128, 0, 0 ],
+                       navy: [ 0, 0, 128 ],
+                       olive: [ 128, 128, 0 ],
+                       orange: [ 255, 165, 0 ],
+                       pink: [ 255, 192, 203 ],
+                       purple: [ 128, 0, 128 ],
+                       violet: [ 128, 0, 128 ],
+                       red: [ 255, 0, 0 ],
+                       silver: [ 192, 192, 192 ],
+                       white: [ 255, 255, 255 ],
+                       yellow: [ 255, 255, 0 ],
+                       transparent: [ 255, 255, 255 ]
+               },
+
+               /**
+                * Convert an RGB color value to HSL.
+                *
+                * Conversion formula based on
+                * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
+                *
+                * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
+                *
+                * Assumes `r`, `g`, and `b` are contained in the set `[0, 255]` and
+                * returns `h`, `s`, and `l` in the set `[0, 1]`.
+                *
+                * @param {number} r The red color value
+                * @param {number} g The green color value
+                * @param {number} b The blue color value
+                * @return {number[]} The HSL representation
+                */
+               rgbToHsl: function ( r, g, b ) {
+                       var d, h, s, l, min, max;
+
+                       r = r / 255;
+                       g = g / 255;
+                       b = b / 255;
+
+                       max = Math.max( r, g, b );
+                       min = Math.min( r, g, b );
+                       l = ( max + min ) / 2;
+
+                       if ( max === min ) {
+                               // achromatic
+                               h = s = 0;
+                       } else {
+                               d = max - min;
+                               s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min );
+                               switch ( max ) {
+                                       case r:
+                                               h = ( g - b ) / d + ( g < b ? 6 : 0 );
+                                               break;
+                                       case g:
+                                               h = ( b - r ) / d + 2;
+                                               break;
+                                       case b:
+                                               h = ( r - g ) / d + 4;
+                                               break;
+                               }
+                               h /= 6;
+                       }
+
+                       return [ h, s, l ];
+               },
+
+               /**
+                * Convert an HSL color value to RGB.
+                *
+                * Conversion formula based on
+                * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
+                *
+                * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
+                *
+                * Assumes `h`, `s`, and `l` are contained in the set `[0, 1]` and
+                * returns `r`, `g`, and `b` in the set `[0, 255]`.
+                *
+                * @param {number} h The hue
+                * @param {number} s The saturation
+                * @param {number} l The lightness
+                * @return {number[]} The RGB representation
+                */
+               hslToRgb: function ( h, s, l ) {
+                       var r, g, b, hue2rgb, q, p;
+
+                       if ( s === 0 ) {
+                               r = g = b = l; // achromatic
+                       } else {
+                               hue2rgb = function ( p, q, t ) {
+                                       if ( t < 0 ) {
+                                               t += 1;
+                                       }
+                                       if ( t > 1 ) {
+                                               t -= 1;
+                                       }
+                                       if ( t < 1 / 6 ) {
+                                               return p + ( q - p ) * 6 * t;
+                                       }
+                                       if ( t < 1 / 2 ) {
+                                               return q;
+                                       }
+                                       if ( t < 2 / 3 ) {
+                                               return p + ( q - p ) * ( 2 / 3 - t ) * 6;
+                                       }
+                                       return p;
+                               };
+
+                               q = l < 0.5 ? l * ( 1 + s ) : l + s - l * s;
+                               p = 2 * l - q;
+                               r = hue2rgb( p, q, h + 1 / 3 );
+                               g = hue2rgb( p, q, h );
+                               b = hue2rgb( p, q, h - 1 / 3 );
+                       }
+
+                       return [ r * 255, g * 255, b * 255 ];
+               },
+
+               /**
+                * Get a brighter or darker rgb() value string.
+                *
+                * Usage:
+                *
+                *     $.colorUtil.getColorBrightness( 'red', +0.1 );
+                *     // > "rgb(255,50,50)"
+                *     $.colorUtil.getColorBrightness( 'rgb(200,50,50)', -0.2 );
+                *     // > "rgb(118,29,29)"
+                *
+                * @param {Mixed} currentColor Current value in css
+                * @param {number} mod Wanted brightness modification between -1 and 1
+                * @return {string} Like `'rgb(r,g,b)'`
+                */
+               getColorBrightness: function ( currentColor, mod ) {
+                       var rgbArr = $.colorUtil.getRGB( currentColor ),
+                               hslArr = $.colorUtil.rgbToHsl( rgbArr[ 0 ], rgbArr[ 1 ], rgbArr[ 2 ] );
+                       rgbArr = $.colorUtil.hslToRgb( hslArr[ 0 ], hslArr[ 1 ], hslArr[ 2 ] + mod );
+
+                       return 'rgb(' +
+                               [ parseInt( rgbArr[ 0 ], 10 ), parseInt( rgbArr[ 1 ], 10 ), parseInt( rgbArr[ 2 ], 10 ) ].join( ',' ) +
+                               ')';
+               }
+
+       };
+
+}() );
diff --git a/resources/src/jquery/jquery.color.js b/resources/src/jquery/jquery.color.js
deleted file mode 100644 (file)
index 6df02ad..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * jQuery Color Animations
- *
- * @author John Resig, 2007
- * @author Krinkle, 2011
- * Released under the MIT and GPL licenses.
- *
- * - 2011-01-05: Forked for MediaWiki. See also jQuery.colorUtil plugin
- */
-( function () {
-
-       function getColor( elem, attr ) {
-               var color;
-
-               do {
-                       color = $.css( elem, attr );
-
-                       // Keep going until we find an element that has color, or we hit the body
-                       if ( color !== '' && color !== 'transparent' || elem.nodeName.toLowerCase() === 'body' ) {
-                               break;
-                       }
-
-                       attr = 'backgroundColor';
-               // eslint-disable-next-line no-cond-assign
-               } while ( elem = elem.parentNode );
-
-               return $.colorUtil.getRGB( color );
-       }
-
-       // We override the animation for all of these color styles
-       [
-               'backgroundColor',
-               'borderBottomColor',
-               'borderLeftColor',
-               'borderRightColor',
-               'borderTopColor',
-               'color',
-               'outlineColor'
-       ].forEach( function ( attr ) {
-               $.fx.step[ attr ] = function ( fx ) {
-                       if ( !fx.colorInit ) {
-                               fx.start = getColor( fx.elem, attr );
-                               fx.end = $.colorUtil.getRGB( fx.end );
-                               fx.colorInit = true;
-                       }
-
-                       fx.elem.style[ attr ] = 'rgb(' + [
-                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 0 ] - fx.start[ 0 ] ) ) + fx.start[ 0 ], 10 ), 255 ), 0 ),
-                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 1 ] - fx.start[ 1 ] ) ) + fx.start[ 1 ], 10 ), 255 ), 0 ),
-                               Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 2 ] - fx.start[ 2 ] ) ) + fx.start[ 2 ], 10 ), 255 ), 0 )
-                       ].join( ',' ) + ')';
-               };
-       } );
-
-}() );
diff --git a/resources/src/jquery/jquery.colorUtil.js b/resources/src/jquery/jquery.colorUtil.js
deleted file mode 100644 (file)
index 009be1a..0000000
+++ /dev/null
@@ -1,268 +0,0 @@
-/*!
- * jQuery Color Utilities
- *
- * Released under the MIT and GPL licenses.
- *
- * Mostly based on other plugins and functions (linted and optimized a little).
- * Sources cited inline.
- */
-( function () {
-       /**
-        * @class jQuery.colorUtil
-        * @singleton
-        */
-       $.colorUtil = {
-
-               /**
-                * Parse CSS color strings looking for color tuples
-                *
-                * Based on highlightFade by Blair Mitchelmore
-                * <http://jquery.offput.ca/highlightFade/>
-                *
-                * @param {Array|string} color
-                * @return {Array}
-                */
-               getRGB: function ( color ) {
-                       var result;
-
-                       // Check if we're already dealing with an array of colors
-                       if ( color && Array.isArray( color ) && color.length === 3 ) {
-                               return color;
-                       }
-                       if ( typeof color !== 'string' ) {
-                               return undefined;
-                       }
-
-                       // Look for rgb(num,num,num)
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec( color ) ) {
-                               return [
-                                       parseInt( result[ 1 ], 10 ),
-                                       parseInt( result[ 2 ], 10 ),
-                                       parseInt( result[ 3 ], 10 )
-                               ];
-                       }
-
-                       // Look for rgb(num%,num%,num%)
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*\)/.exec( color ) ) {
-                               return [
-                                       parseFloat( result[ 1 ] ) * 2.55,
-                                       parseFloat( result[ 2 ] ) * 2.55,
-                                       parseFloat( result[ 3 ] ) * 2.55
-                               ];
-                       }
-
-                       // Look for #a0b1c2
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec( color ) ) {
-                               return [
-                                       parseInt( result[ 1 ], 16 ),
-                                       parseInt( result[ 2 ], 16 ),
-                                       parseInt( result[ 3 ], 16 )
-                               ];
-                       }
-
-                       // Look for #fff
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec( color ) ) {
-                               return [
-                                       parseInt( result[ 1 ] + result[ 1 ], 16 ),
-                                       parseInt( result[ 2 ] + result[ 2 ], 16 ),
-                                       parseInt( result[ 3 ] + result[ 3 ], 16 )
-                               ];
-                       }
-
-                       // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
-                       // eslint-disable-next-line no-cond-assign
-                       if ( result = /rgba\(0, 0, 0, 0\)/.exec( color ) ) {
-                               return $.colorUtil.colors.transparent;
-                       }
-
-                       // Otherwise, we're most likely dealing with a named color
-                       return $.colorUtil.colors[ color.trim().toLowerCase() ];
-               },
-
-               /**
-                * Named color map
-                *
-                * Based on Interface by Stefan Petre
-                * <http://interface.eyecon.ro/>
-                *
-                * @property {Object}
-                */
-               colors: {
-                       aqua: [ 0, 255, 255 ],
-                       azure: [ 240, 255, 255 ],
-                       beige: [ 245, 245, 220 ],
-                       black: [ 0, 0, 0 ],
-                       blue: [ 0, 0, 255 ],
-                       brown: [ 165, 42, 42 ],
-                       cyan: [ 0, 255, 255 ],
-                       darkblue: [ 0, 0, 139 ],
-                       darkcyan: [ 0, 139, 139 ],
-                       darkgrey: [ 169, 169, 169 ],
-                       darkgreen: [ 0, 100, 0 ],
-                       darkkhaki: [ 189, 183, 107 ],
-                       darkmagenta: [ 139, 0, 139 ],
-                       darkolivegreen: [ 85, 107, 47 ],
-                       darkorange: [ 255, 140, 0 ],
-                       darkorchid: [ 153, 50, 204 ],
-                       darkred: [ 139, 0, 0 ],
-                       darksalmon: [ 233, 150, 122 ],
-                       darkviolet: [ 148, 0, 211 ],
-                       fuchsia: [ 255, 0, 255 ],
-                       gold: [ 255, 215, 0 ],
-                       green: [ 0, 128, 0 ],
-                       indigo: [ 75, 0, 130 ],
-                       khaki: [ 240, 230, 140 ],
-                       lightblue: [ 173, 216, 230 ],
-                       lightcyan: [ 224, 255, 255 ],
-                       lightgreen: [ 144, 238, 144 ],
-                       lightgrey: [ 211, 211, 211 ],
-                       lightpink: [ 255, 182, 193 ],
-                       lightyellow: [ 255, 255, 224 ],
-                       lime: [ 0, 255, 0 ],
-                       magenta: [ 255, 0, 255 ],
-                       maroon: [ 128, 0, 0 ],
-                       navy: [ 0, 0, 128 ],
-                       olive: [ 128, 128, 0 ],
-                       orange: [ 255, 165, 0 ],
-                       pink: [ 255, 192, 203 ],
-                       purple: [ 128, 0, 128 ],
-                       violet: [ 128, 0, 128 ],
-                       red: [ 255, 0, 0 ],
-                       silver: [ 192, 192, 192 ],
-                       white: [ 255, 255, 255 ],
-                       yellow: [ 255, 255, 0 ],
-                       transparent: [ 255, 255, 255 ]
-               },
-
-               /**
-                * Convert an RGB color value to HSL.
-                *
-                * Conversion formula based on
-                * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
-                *
-                * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
-                *
-                * Assumes `r`, `g`, and `b` are contained in the set `[0, 255]` and
-                * returns `h`, `s`, and `l` in the set `[0, 1]`.
-                *
-                * @param {number} r The red color value
-                * @param {number} g The green color value
-                * @param {number} b The blue color value
-                * @return {number[]} The HSL representation
-                */
-               rgbToHsl: function ( r, g, b ) {
-                       var d, h, s, l, min, max;
-
-                       r = r / 255;
-                       g = g / 255;
-                       b = b / 255;
-
-                       max = Math.max( r, g, b );
-                       min = Math.min( r, g, b );
-                       l = ( max + min ) / 2;
-
-                       if ( max === min ) {
-                               // achromatic
-                               h = s = 0;
-                       } else {
-                               d = max - min;
-                               s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min );
-                               switch ( max ) {
-                                       case r:
-                                               h = ( g - b ) / d + ( g < b ? 6 : 0 );
-                                               break;
-                                       case g:
-                                               h = ( b - r ) / d + 2;
-                                               break;
-                                       case b:
-                                               h = ( r - g ) / d + 4;
-                                               break;
-                               }
-                               h /= 6;
-                       }
-
-                       return [ h, s, l ];
-               },
-
-               /**
-                * Convert an HSL color value to RGB.
-                *
-                * Conversion formula based on
-                * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
-                *
-                * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
-                *
-                * Assumes `h`, `s`, and `l` are contained in the set `[0, 1]` and
-                * returns `r`, `g`, and `b` in the set `[0, 255]`.
-                *
-                * @param {number} h The hue
-                * @param {number} s The saturation
-                * @param {number} l The lightness
-                * @return {number[]} The RGB representation
-                */
-               hslToRgb: function ( h, s, l ) {
-                       var r, g, b, hue2rgb, q, p;
-
-                       if ( s === 0 ) {
-                               r = g = b = l; // achromatic
-                       } else {
-                               hue2rgb = function ( p, q, t ) {
-                                       if ( t < 0 ) {
-                                               t += 1;
-                                       }
-                                       if ( t > 1 ) {
-                                               t -= 1;
-                                       }
-                                       if ( t < 1 / 6 ) {
-                                               return p + ( q - p ) * 6 * t;
-                                       }
-                                       if ( t < 1 / 2 ) {
-                                               return q;
-                                       }
-                                       if ( t < 2 / 3 ) {
-                                               return p + ( q - p ) * ( 2 / 3 - t ) * 6;
-                                       }
-                                       return p;
-                               };
-
-                               q = l < 0.5 ? l * ( 1 + s ) : l + s - l * s;
-                               p = 2 * l - q;
-                               r = hue2rgb( p, q, h + 1 / 3 );
-                               g = hue2rgb( p, q, h );
-                               b = hue2rgb( p, q, h - 1 / 3 );
-                       }
-
-                       return [ r * 255, g * 255, b * 255 ];
-               },
-
-               /**
-                * Get a brighter or darker rgb() value string.
-                *
-                * Usage:
-                *
-                *     $.colorUtil.getColorBrightness( 'red', +0.1 );
-                *     // > "rgb(255,50,50)"
-                *     $.colorUtil.getColorBrightness( 'rgb(200,50,50)', -0.2 );
-                *     // > "rgb(118,29,29)"
-                *
-                * @param {Mixed} currentColor Current value in css
-                * @param {number} mod Wanted brightness modification between -1 and 1
-                * @return {string} Like `'rgb(r,g,b)'`
-                */
-               getColorBrightness: function ( currentColor, mod ) {
-                       var rgbArr = $.colorUtil.getRGB( currentColor ),
-                               hslArr = $.colorUtil.rgbToHsl( rgbArr[ 0 ], rgbArr[ 1 ], rgbArr[ 2 ] );
-                       rgbArr = $.colorUtil.hslToRgb( hslArr[ 0 ], hslArr[ 1 ], hslArr[ 2 ] + mod );
-
-                       return 'rgb(' +
-                               [ parseInt( rgbArr[ 0 ], 10 ), parseInt( rgbArr[ 1 ], 10 ), parseInt( rgbArr[ 2 ], 10 ) ].join( ',' ) +
-                               ')';
-               }
-
-       };
-
-}() );
index 4b6313b..83ea0ce 100644 (file)
@@ -59,7 +59,6 @@
                                        }
                                },
                                parameters: {
-                                       // Add 'origin' query parameter to all requests.
                                        origin: this.getOrigin()
                                }
                        },
         * any).
         *
         * @protected
-        * @return {string}
+        * @return {string|undefined}
         */
        CoreForeignApi.prototype.getOrigin = function () {
-               var origin;
+               var origin, apiUri, apiOrigin;
                if ( this.anonymous ) {
                        return '*';
                }
+
                origin = location.protocol + '//' + location.hostname;
                if ( location.port ) {
                        origin += ':' + location.port;
                }
+
+               apiUri = new mw.Uri( this.apiUrl );
+               apiOrigin = apiUri.protocol + '://' + apiUri.getAuthority();
+               if ( origin === apiOrigin ) {
+                       // requests are not cross-origin, omit parameter
+                       return undefined;
+               }
+
                return origin;
        };
 
                if ( ajaxOptions.type === 'POST' ) {
                        url = ( ajaxOptions && ajaxOptions.url ) || this.defaults.ajax.url;
                        origin = ( parameters && parameters.origin ) || this.defaults.parameters.origin;
-                       url += ( url.indexOf( '?' ) !== -1 ? '&' : '?' ) +
-                               // Depending on server configuration, MediaWiki may forbid periods in URLs, due to an IE 6
-                               // XSS bug. So let's escape them here. See WebRequest::checkUrlExtension() and T30235.
-                               'origin=' + encodeURIComponent( origin ).replace( /\./g, '%2E' );
+                       if ( origin !== undefined ) {
+                               url += ( url.indexOf( '?' ) !== -1 ? '&' : '?' ) +
+                                       // Depending on server configuration, MediaWiki may forbid periods in URLs, due to an IE 6
+                                       // XSS bug. So let's escape them here. See WebRequest::checkUrlExtension() and T30235.
+                                       'origin=' + encodeURIComponent( origin ).replace( /\./g, '%2E' );
+                       }
                        newAjaxOptions = $.extend( {}, ajaxOptions, { url: url } );
                } else {
                        newAjaxOptions = ajaxOptions;
diff --git a/resources/src/mediawiki.RegExp.js b/resources/src/mediawiki.RegExp.js
deleted file mode 100644 (file)
index 258bc2c..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-( function () {
-       mw.RegExp = {};
-       // Backwards-compatible alias; @deprecated since 1.34
-       mw.log.deprecate( mw.RegExp, 'escape', mw.util.escapeRegExp, 'Use mw.util.escapeRegExp() instead.', 'mw.RegExp.escape' );
-}() );
index 3084e12..3f39fd1 100644 (file)
@@ -137,11 +137,11 @@ var
                '[^' + mw.config.get( 'wgLegalTitleChars' ) + ']' +
                // URL percent encoding sequences interfere with the ability
                // to round-trip titles -- you can't link to them consistently.
-               '|%[0-9A-Fa-f]{2}' +
+               '|%[\\dA-Fa-f]{2}' +
                // XML/HTML character references produce similar issues.
-               '|&[A-Za-z0-9\u0080-\uFFFF]+;' +
-               '|&#[0-9]+;' +
-               '|&#x[0-9A-Fa-f]+;'
+               '|&[\\dA-Za-z\u0080-\uFFFF]+;' +
+               '|&#\\d+;' +
+               '|&#x[\\dA-Fa-f]+;'
        ),
 
        // From MediaWikiTitleCodec::splitTitleString() in PHP
@@ -149,7 +149,7 @@ var
        rWhitespace = /[ _\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]+/g,
 
        // From MediaWikiTitleCodec::splitTitleString() in PHP
-       rUnicodeBidi = /[\u200E\u200F\u202A-\u202E]/g,
+       rUnicodeBidi = /[\u200E\u200F\u202A-\u202E]+/g,
 
        /**
         * Slightly modified from Flinfo. Credit goes to Lupo and Flominator.
@@ -173,13 +173,13 @@ var
                },
                // URL encoding (possibly)
                {
-                       pattern: /%([0-9A-Fa-f]{2})/g,
+                       pattern: /%([\dA-Fa-f]{2})/g,
                        replace: '% $1',
                        generalRule: true
                },
                // HTML-character-entities
                {
-                       pattern: /&(([A-Za-z0-9\x80-\xff]+|#[0-9]+|#x[0-9A-Fa-f]+);)/g,
+                       pattern: /&(([\dA-Za-z\x80-\xff]+|#\d+|#x[\dA-Fa-f]+);)/g,
                        replace: '& $1',
                        generalRule: true
                },
@@ -228,7 +228,7 @@ var
         * @return {Object|boolean}
         */
        parse = function ( title, defaultNamespace ) {
-               var namespace, m, id, i, fragment, ext;
+               var namespace, m, id, i, fragment;
 
                namespace = defaultNamespace === undefined ? NS_MAIN : defaultNamespace;
 
@@ -294,7 +294,7 @@ var
                }
 
                // Reject illegal characters
-               if ( title.match( rInvalid ) ) {
+               if ( rInvalid.test( title ) ) {
                        return false;
                }
 
@@ -336,21 +336,9 @@ var
                        return false;
                }
 
-               // For backwards-compatibility with old mw.Title, we separate the extension from the
-               // rest of the title.
-               i = title.lastIndexOf( '.' );
-               if ( i === -1 || title.length <= i + 1 ) {
-                       // Extensions are the non-empty segment after the last dot
-                       ext = null;
-               } else {
-                       ext = title.slice( i + 1 );
-                       title = title.slice( 0, i );
-               }
-
                return {
                        namespace: namespace,
                        title: title,
-                       ext: ext,
                        fragment: fragment
                };
        },
@@ -438,7 +426,6 @@ function Title( title, namespace ) {
 
        this.namespace = parsed.namespace;
        this.title = parsed.title;
-       this.ext = parsed.ext;
        this.fragment = parsed.fragment;
 }
 
@@ -465,7 +452,6 @@ Title.newFromText = function ( title, namespace ) {
        t = Object.create( Title.prototype );
        t.namespace = parsed.namespace;
        t.title = parsed.title;
-       t.ext = parsed.ext;
        t.fragment = parsed.fragment;
 
        return t;
@@ -600,7 +586,6 @@ Title.newFromUserInput = function ( title, defaultNamespaceOrOptions, options )
  * @return {mw.Title|null} A valid Title object or null if the title is invalid
  */
 Title.newFromFileName = function ( uncleanName ) {
-
        return Title.newFromUserInput( 'File:' + uncleanName, {
                forUploading: true
        } );
@@ -622,10 +607,10 @@ Title.newFromImg = function ( img ) {
                thumbPhpRegex = /thumb\.php/,
                regexes = [
                        // Thumbnails
-                       /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s/]+)\/[^\s/]+-[^\s/]*$/,
+                       /\/[\da-f]\/[\da-f]{2}\/([^\s/]+)\/[^\s/]+-[^\s/]*$/,
 
                        // Full size images
-                       /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s/]+)$/,
+                       /\/[\da-f]\/[\da-f]{2}\/([^\s/]+)$/,
 
                        // Thumbnails in non-hashed upload directories
                        /\/([^\s/]+)\/[^\s/]+-(?:\1|thumbnail)[^\s/]*$/,
@@ -638,9 +623,7 @@ Title.newFromImg = function ( img ) {
 
        src = img.jquery ? img[ 0 ].src : img.src;
 
-       matches = src.match( thumbPhpRegex );
-
-       if ( matches ) {
+       if ( thumbPhpRegex.test( src ) ) {
                return mw.Title.newFromText( 'File:' + mw.util.getParamValue( 'f', src ) );
        }
 
@@ -759,16 +742,16 @@ Title.exist = {
 Title.normalizeExtension = function ( extension ) {
        var
                lower = extension.toLowerCase(),
-               squish = {
+               normalizations = {
                        htm: 'html',
                        jpeg: 'jpg',
                        mpeg: 'mpg',
                        tiff: 'tif',
                        ogv: 'ogg'
                };
-       if ( Object.prototype.hasOwnProperty.call( squish, lower ) ) {
-               return squish[ lower ];
-       } else if ( /^[0-9a-z]+$/.test( lower ) ) {
+       if ( Object.hasOwnProperty.call( normalizations, lower ) ) {
+               return normalizations[ lower ];
+       } else if ( /^[\da-z]+$/.test( lower ) ) {
                return lower;
        } else {
                return '';
@@ -824,13 +807,11 @@ Title.prototype = {
         * @return {string}
         */
        getName: function () {
-               if (
-                       mw.config.get( 'wgCaseSensitiveNamespaces' ).indexOf( this.namespace ) !== -1 ||
-                       !this.title.length
-               ) {
-                       return this.title;
+               var ext = this.getExtension();
+               if ( ext === null ) {
+                       return this.getMain();
                }
-               return mw.Title.phpCharToUpper( this.title[ 0 ] ) + this.title.slice( 1 );
+               return this.getMain().slice( 0, -ext.length - 1 );
        },
 
        /**
@@ -852,7 +833,11 @@ Title.prototype = {
         * @return {string|null} Name extension or null if there is none
         */
        getExtension: function () {
-               return this.ext;
+               var lastDot = this.title.lastIndexOf( '.' );
+               if ( lastDot === -1 ) {
+                       return null;
+               }
+               return this.title.slice( lastDot + 1 ) || null;
        },
 
        /**
@@ -863,7 +848,8 @@ Title.prototype = {
         * @return {string}
         */
        getDotExtension: function () {
-               return this.ext === null ? '' : '.' + this.ext;
+               var ext = this.getExtension();
+               return ext === null ? '' : '.' + ext;
        },
 
        /**
@@ -874,7 +860,13 @@ Title.prototype = {
         * @return {string}
         */
        getMain: function () {
-               return this.getName() + this.getDotExtension();
+               if (
+                       mw.config.get( 'wgCaseSensitiveNamespaces' ).indexOf( this.namespace ) !== -1 ||
+                       !this.title.length
+               ) {
+                       return this.title;
+               }
+               return mw.Title.phpCharToUpper( this.title[ 0 ] ) + this.title.slice( 1 );
        },
 
        /**
index b0887fa..2ba08cf 100644 (file)
@@ -1,6 +1,8 @@
 {
        "ß": "ß",
        "ʼn": "ʼn",
+       "ƀ": "ƀ",
+       "ƚ": "ƚ",
        "Dž": "Dž",
        "dž": "Dž",
        "Lj": "Lj",
        "ǰ": "ǰ",
        "Dz": "Dz",
        "dz": "Dz",
-       "ʝ": "Ʝ",
+       "ȼ": "ȼ",
+       "ȿ": "ȿ",
+       "ɀ": "ɀ",
+       "ɂ": "ɂ",
+       "ɇ": "ɇ",
+       "ɉ": "ɉ",
+       "ɋ": "ɋ",
+       "ɍ": "ɍ",
+       "ɏ": "ɏ",
+       "ɐ": "ɐ",
+       "ɑ": "ɑ",
+       "ɒ": "ɒ",
+       "ɜ": "ɜ",
+       "ɡ": "ɡ",
+       "ɥ": "ɥ",
+       "ɦ": "ɦ",
+       "ɪ": "ɪ",
+       "ɫ": "ɫ",
+       "ɬ": "ɬ",
+       "ɱ": "ɱ",
+       "ɽ": "ɽ",
+       "ʂ": "ʂ",
+       "ʇ": "ʇ",
+       "ʉ": "ʉ",
+       "ʌ": "ʌ",
+       "ʝ": "ʝ",
+       "ʞ": "ʞ",
        "ͅ": "ͅ",
+       "ͱ": "ͱ",
+       "ͳ": "ͳ",
+       "ͷ": "ͷ",
+       "ͻ": "ͻ",
+       "ͼ": "ͼ",
+       "ͽ": "ͽ",
        "ΐ": "ΐ",
        "ΰ": "ΰ",
+       "ϗ": "ϗ",
+       "ϲ": "Σ",
+       "ϳ": "ϳ",
+       "ϸ": "ϸ",
+       "ϻ": "ϻ",
+       "ӏ": "ӏ",
+       "ӷ": "ӷ",
+       "ӻ": "ӻ",
+       "ӽ": "ӽ",
+       "ӿ": "ӿ",
+       "ԑ": "ԑ",
+       "ԓ": "ԓ",
+       "ԕ": "ԕ",
+       "ԗ": "ԗ",
+       "ԙ": "ԙ",
+       "ԛ": "ԛ",
+       "ԝ": "ԝ",
+       "ԟ": "ԟ",
+       "ԡ": "ԡ",
+       "ԣ": "ԣ",
+       "ԥ": "ԥ",
+       "ԧ": "ԧ",
+       "ԩ": "ԩ",
+       "ԫ": "ԫ",
+       "ԭ": "ԭ",
+       "ԯ": "ԯ",
        "և": "և",
-       "ᏸ": "Ᏸ",
-       "ᏹ": "Ᏹ",
-       "ᏺ": "Ᏺ",
-       "ᏻ": "Ᏻ",
-       "ᏼ": "Ᏼ",
-       "ᏽ": "Ᏽ",
+       "ა": "ა",
+       "ბ": "ბ",
+       "გ": "გ",
+       "დ": "დ",
+       "ე": "ე",
+       "ვ": "ვ",
+       "ზ": "ზ",
+       "თ": "თ",
+       "ი": "ი",
+       "კ": "კ",
+       "ლ": "ლ",
+       "მ": "მ",
+       "ნ": "ნ",
+       "ო": "ო",
+       "პ": "პ",
+       "ჟ": "ჟ",
+       "რ": "რ",
+       "ს": "ს",
+       "ტ": "ტ",
+       "უ": "უ",
+       "ფ": "ფ",
+       "ქ": "ქ",
+       "ღ": "ღ",
+       "ყ": "ყ",
+       "შ": "შ",
+       "ჩ": "ჩ",
+       "ც": "ც",
+       "ძ": "ძ",
+       "წ": "წ",
+       "ჭ": "ჭ",
+       "ხ": "ხ",
+       "ჯ": "ჯ",
+       "ჰ": "ჰ",
+       "ჱ": "ჱ",
+       "ჲ": "ჲ",
+       "ჳ": "ჳ",
+       "ჴ": "ჴ",
+       "ჵ": "ჵ",
+       "ჶ": "ჶ",
+       "ჷ": "ჷ",
+       "ჸ": "ჸ",
+       "ჹ": "ჹ",
+       "ჺ": "ჺ",
+       "ჽ": "ჽ",
+       "ჾ": "ჾ",
+       "ჿ": "ჿ",
+       "ᏸ": "ᏸ",
+       "ᏹ": "ᏹ",
+       "ᏺ": "ᏺ",
+       "ᏻ": "ᏻ",
+       "ᏼ": "ᏼ",
+       "ᏽ": "ᏽ",
+       "ᲀ": "ᲀ",
+       "ᲁ": "ᲁ",
+       "ᲂ": "ᲂ",
+       "ᲃ": "ᲃ",
+       "ᲄ": "ᲄ",
+       "ᲅ": "ᲅ",
+       "ᲆ": "ᲆ",
+       "ᲇ": "ᲇ",
+       "ᲈ": "ᲈ",
+       "ᵹ": "ᵹ",
+       "ᵽ": "ᵽ",
+       "ᶎ": "ᶎ",
        "ẖ": "ẖ",
        "ẗ": "ẗ",
        "ẘ": "ẘ",
        "ẙ": "ẙ",
        "ẚ": "ẚ",
+       "ỻ": "ỻ",
+       "ỽ": "ỽ",
+       "ỿ": "ỿ",
        "ὐ": "ὐ",
        "ὒ": "ὒ",
        "ὔ": "ὔ",
        "ῶ": "ῶ",
        "ῷ": "ῷ",
        "ῼ": "ῼ",
+       "ⅎ": "ⅎ",
        "ⅰ": "ⅰ",
        "ⅱ": "ⅱ",
        "ⅲ": "ⅲ",
        "ⅽ": "ⅽ",
        "ⅾ": "ⅾ",
        "ⅿ": "ⅿ",
+       "ↄ": "ↄ",
        "ⓐ": "ⓐ",
        "ⓑ": "ⓑ",
        "ⓒ": "ⓒ",
        "ⓧ": "ⓧ",
        "ⓨ": "ⓨ",
        "ⓩ": "ⓩ",
-       "ꞵ": "Ꞵ",
-       "ꞷ": "Ꞷ",
-       "ꭓ": "Ꭓ",
-       "ꭰ": "Ꭰ",
-       "ꭱ": "Ꭱ",
-       "ꭲ": "Ꭲ",
-       "ꭳ": "Ꭳ",
-       "ꭴ": "Ꭴ",
-       "ꭵ": "Ꭵ",
-       "ꭶ": "Ꭶ",
-       "ꭷ": "Ꭷ",
-       "ꭸ": "Ꭸ",
-       "ꭹ": "Ꭹ",
-       "ꭺ": "Ꭺ",
-       "ꭻ": "Ꭻ",
-       "ꭼ": "Ꭼ",
-       "ꭽ": "Ꭽ",
-       "ꭾ": "Ꭾ",
-       "ꭿ": "Ꭿ",
-       "ꮀ": "Ꮀ",
-       "ꮁ": "Ꮁ",
-       "ꮂ": "Ꮂ",
-       "ꮃ": "Ꮃ",
-       "ꮄ": "Ꮄ",
-       "ꮅ": "Ꮅ",
-       "ꮆ": "Ꮆ",
-       "ꮇ": "Ꮇ",
-       "ꮈ": "Ꮈ",
-       "ꮉ": "Ꮉ",
-       "ꮊ": "Ꮊ",
-       "ꮋ": "Ꮋ",
-       "ꮌ": "Ꮌ",
-       "ꮍ": "Ꮍ",
-       "ꮎ": "Ꮎ",
-       "ꮏ": "Ꮏ",
-       "ꮐ": "Ꮐ",
-       "ꮑ": "Ꮑ",
-       "ꮒ": "Ꮒ",
-       "ꮓ": "Ꮓ",
-       "ꮔ": "Ꮔ",
-       "ꮕ": "Ꮕ",
-       "ꮖ": "Ꮖ",
-       "ꮗ": "Ꮗ",
-       "ꮘ": "Ꮘ",
-       "ꮙ": "Ꮙ",
-       "ꮚ": "Ꮚ",
-       "ꮛ": "Ꮛ",
-       "ꮜ": "Ꮜ",
-       "ꮝ": "Ꮝ",
-       "ꮞ": "Ꮞ",
-       "ꮟ": "Ꮟ",
-       "ꮠ": "Ꮠ",
-       "ꮡ": "Ꮡ",
-       "ꮢ": "Ꮢ",
-       "ꮣ": "Ꮣ",
-       "ꮤ": "Ꮤ",
-       "ꮥ": "Ꮥ",
-       "ꮦ": "Ꮦ",
-       "ꮧ": "Ꮧ",
-       "ꮨ": "Ꮨ",
-       "ꮩ": "Ꮩ",
-       "ꮪ": "Ꮪ",
-       "ꮫ": "Ꮫ",
-       "ꮬ": "Ꮬ",
-       "ꮭ": "Ꮭ",
-       "ꮮ": "Ꮮ",
-       "ꮯ": "Ꮯ",
-       "ꮰ": "Ꮰ",
-       "ꮱ": "Ꮱ",
-       "ꮲ": "Ꮲ",
-       "ꮳ": "Ꮳ",
-       "ꮴ": "Ꮴ",
-       "ꮵ": "Ꮵ",
-       "ꮶ": "Ꮶ",
-       "ꮷ": "Ꮷ",
-       "ꮸ": "Ꮸ",
-       "ꮹ": "Ꮹ",
-       "ꮺ": "Ꮺ",
-       "ꮻ": "Ꮻ",
-       "ꮼ": "Ꮼ",
-       "ꮽ": "Ꮽ",
-       "ꮾ": "Ꮾ",
-       "ꮿ": "Ꮿ",
+       "ⰰ": "ⰰ",
+       "ⰱ": "ⰱ",
+       "ⰲ": "ⰲ",
+       "ⰳ": "ⰳ",
+       "ⰴ": "ⰴ",
+       "ⰵ": "ⰵ",
+       "ⰶ": "ⰶ",
+       "ⰷ": "ⰷ",
+       "ⰸ": "ⰸ",
+       "ⰹ": "ⰹ",
+       "ⰺ": "ⰺ",
+       "ⰻ": "ⰻ",
+       "ⰼ": "ⰼ",
+       "ⰽ": "ⰽ",
+       "ⰾ": "ⰾ",
+       "ⰿ": "ⰿ",
+       "ⱀ": "ⱀ",
+       "ⱁ": "ⱁ",
+       "ⱂ": "ⱂ",
+       "ⱃ": "ⱃ",
+       "ⱄ": "ⱄ",
+       "ⱅ": "ⱅ",
+       "ⱆ": "ⱆ",
+       "ⱇ": "ⱇ",
+       "ⱈ": "ⱈ",
+       "ⱉ": "ⱉ",
+       "ⱊ": "ⱊ",
+       "ⱋ": "ⱋ",
+       "ⱌ": "ⱌ",
+       "ⱍ": "ⱍ",
+       "ⱎ": "ⱎ",
+       "ⱏ": "ⱏ",
+       "ⱐ": "ⱐ",
+       "ⱑ": "ⱑ",
+       "ⱒ": "ⱒ",
+       "ⱓ": "ⱓ",
+       "ⱔ": "ⱔ",
+       "ⱕ": "ⱕ",
+       "ⱖ": "ⱖ",
+       "ⱗ": "ⱗ",
+       "ⱘ": "ⱘ",
+       "ⱙ": "ⱙ",
+       "ⱚ": "ⱚ",
+       "ⱛ": "ⱛ",
+       "ⱜ": "ⱜ",
+       "ⱝ": "ⱝ",
+       "ⱞ": "ⱞ",
+       "ⱡ": "ⱡ",
+       "ⱥ": "ⱥ",
+       "ⱦ": "ⱦ",
+       "ⱨ": "ⱨ",
+       "ⱪ": "ⱪ",
+       "ⱬ": "ⱬ",
+       "ⱳ": "ⱳ",
+       "ⱶ": "ⱶ",
+       "ⲁ": "ⲁ",
+       "ⲃ": "ⲃ",
+       "ⲅ": "ⲅ",
+       "ⲇ": "ⲇ",
+       "ⲉ": "ⲉ",
+       "ⲋ": "ⲋ",
+       "ⲍ": "ⲍ",
+       "ⲏ": "ⲏ",
+       "ⲑ": "ⲑ",
+       "ⲓ": "ⲓ",
+       "ⲕ": "ⲕ",
+       "ⲗ": "ⲗ",
+       "ⲙ": "ⲙ",
+       "ⲛ": "ⲛ",
+       "ⲝ": "ⲝ",
+       "ⲟ": "ⲟ",
+       "ⲡ": "ⲡ",
+       "ⲣ": "ⲣ",
+       "ⲥ": "ⲥ",
+       "ⲧ": "ⲧ",
+       "ⲩ": "ⲩ",
+       "ⲫ": "ⲫ",
+       "ⲭ": "ⲭ",
+       "ⲯ": "ⲯ",
+       "ⲱ": "ⲱ",
+       "ⲳ": "ⲳ",
+       "ⲵ": "ⲵ",
+       "ⲷ": "ⲷ",
+       "ⲹ": "ⲹ",
+       "ⲻ": "ⲻ",
+       "ⲽ": "ⲽ",
+       "ⲿ": "ⲿ",
+       "ⳁ": "ⳁ",
+       "ⳃ": "ⳃ",
+       "ⳅ": "ⳅ",
+       "ⳇ": "ⳇ",
+       "ⳉ": "ⳉ",
+       "ⳋ": "ⳋ",
+       "ⳍ": "ⳍ",
+       "ⳏ": "ⳏ",
+       "ⳑ": "ⳑ",
+       "ⳓ": "ⳓ",
+       "ⳕ": "ⳕ",
+       "ⳗ": "ⳗ",
+       "ⳙ": "ⳙ",
+       "ⳛ": "ⳛ",
+       "ⳝ": "ⳝ",
+       "ⳟ": "ⳟ",
+       "ⳡ": "ⳡ",
+       "ⳣ": "ⳣ",
+       "ⳬ": "ⳬ",
+       "ⳮ": "ⳮ",
+       "ⳳ": "ⳳ",
+       "ⴀ": "ⴀ",
+       "ⴁ": "ⴁ",
+       "ⴂ": "ⴂ",
+       "ⴃ": "ⴃ",
+       "ⴄ": "ⴄ",
+       "ⴅ": "ⴅ",
+       "ⴆ": "ⴆ",
+       "ⴇ": "ⴇ",
+       "ⴈ": "ⴈ",
+       "ⴉ": "ⴉ",
+       "ⴊ": "ⴊ",
+       "ⴋ": "ⴋ",
+       "ⴌ": "ⴌ",
+       "ⴍ": "ⴍ",
+       "ⴎ": "ⴎ",
+       "ⴏ": "ⴏ",
+       "ⴐ": "ⴐ",
+       "ⴑ": "ⴑ",
+       "ⴒ": "ⴒ",
+       "ⴓ": "ⴓ",
+       "ⴔ": "ⴔ",
+       "ⴕ": "ⴕ",
+       "ⴖ": "ⴖ",
+       "ⴗ": "ⴗ",
+       "ⴘ": "ⴘ",
+       "ⴙ": "ⴙ",
+       "ⴚ": "ⴚ",
+       "ⴛ": "ⴛ",
+       "ⴜ": "ⴜ",
+       "ⴝ": "ⴝ",
+       "ⴞ": "ⴞ",
+       "ⴟ": "ⴟ",
+       "ⴠ": "ⴠ",
+       "ⴡ": "ⴡ",
+       "ⴢ": "ⴢ",
+       "ⴣ": "ⴣ",
+       "ⴤ": "ⴤ",
+       "ⴥ": "ⴥ",
+       "ⴧ": "ⴧ",
+       "ⴭ": "ⴭ",
+       "ꙁ": "ꙁ",
+       "ꙃ": "ꙃ",
+       "ꙅ": "ꙅ",
+       "ꙇ": "ꙇ",
+       "ꙉ": "ꙉ",
+       "ꙋ": "ꙋ",
+       "ꙍ": "ꙍ",
+       "ꙏ": "ꙏ",
+       "ꙑ": "ꙑ",
+       "ꙓ": "ꙓ",
+       "ꙕ": "ꙕ",
+       "ꙗ": "ꙗ",
+       "ꙙ": "ꙙ",
+       "ꙛ": "ꙛ",
+       "ꙝ": "ꙝ",
+       "ꙟ": "ꙟ",
+       "ꙡ": "ꙡ",
+       "ꙣ": "ꙣ",
+       "ꙥ": "ꙥ",
+       "ꙧ": "ꙧ",
+       "ꙩ": "ꙩ",
+       "ꙫ": "ꙫ",
+       "ꙭ": "ꙭ",
+       "ꚁ": "ꚁ",
+       "ꚃ": "ꚃ",
+       "ꚅ": "ꚅ",
+       "ꚇ": "ꚇ",
+       "ꚉ": "ꚉ",
+       "ꚋ": "ꚋ",
+       "ꚍ": "ꚍ",
+       "ꚏ": "ꚏ",
+       "ꚑ": "ꚑ",
+       "ꚓ": "ꚓ",
+       "ꚕ": "ꚕ",
+       "ꚗ": "ꚗ",
+       "ꚙ": "ꚙ",
+       "ꚛ": "ꚛ",
+       "ꜣ": "ꜣ",
+       "ꜥ": "ꜥ",
+       "ꜧ": "ꜧ",
+       "ꜩ": "ꜩ",
+       "ꜫ": "ꜫ",
+       "ꜭ": "ꜭ",
+       "ꜯ": "ꜯ",
+       "ꜳ": "ꜳ",
+       "ꜵ": "ꜵ",
+       "ꜷ": "ꜷ",
+       "ꜹ": "ꜹ",
+       "ꜻ": "ꜻ",
+       "ꜽ": "ꜽ",
+       "ꜿ": "ꜿ",
+       "ꝁ": "ꝁ",
+       "ꝃ": "ꝃ",
+       "ꝅ": "ꝅ",
+       "ꝇ": "ꝇ",
+       "ꝉ": "ꝉ",
+       "ꝋ": "ꝋ",
+       "ꝍ": "ꝍ",
+       "ꝏ": "ꝏ",
+       "ꝑ": "ꝑ",
+       "ꝓ": "ꝓ",
+       "ꝕ": "ꝕ",
+       "ꝗ": "ꝗ",
+       "ꝙ": "ꝙ",
+       "ꝛ": "ꝛ",
+       "ꝝ": "ꝝ",
+       "ꝟ": "ꝟ",
+       "ꝡ": "ꝡ",
+       "ꝣ": "ꝣ",
+       "ꝥ": "ꝥ",
+       "ꝧ": "ꝧ",
+       "ꝩ": "ꝩ",
+       "ꝫ": "ꝫ",
+       "ꝭ": "ꝭ",
+       "ꝯ": "ꝯ",
+       "ꝺ": "ꝺ",
+       "ꝼ": "ꝼ",
+       "ꝿ": "ꝿ",
+       "ꞁ": "ꞁ",
+       "ꞃ": "ꞃ",
+       "ꞅ": "ꞅ",
+       "ꞇ": "ꞇ",
+       "ꞌ": "ꞌ",
+       "ꞑ": "ꞑ",
+       "ꞓ": "ꞓ",
+       "ꞔ": "ꞔ",
+       "ꞗ": "ꞗ",
+       "ꞙ": "ꞙ",
+       "ꞛ": "ꞛ",
+       "ꞝ": "ꞝ",
+       "ꞟ": "ꞟ",
+       "ꞡ": "ꞡ",
+       "ꞣ": "ꞣ",
+       "ꞥ": "ꞥ",
+       "ꞧ": "ꞧ",
+       "ꞩ": "ꞩ",
+       "ꞵ": "ꞵ",
+       "ꞷ": "ꞷ",
+       "ꞹ": "ꞹ",
+       "ꞻ": "ꞻ",
+       "ꞽ": "ꞽ",
+       "ꞿ": "ꞿ",
+       "ꟃ": "ꟃ",
+       "ꭓ": "ꭓ",
+       "ꭰ": "ꭰ",
+       "ꭱ": "ꭱ",
+       "ꭲ": "ꭲ",
+       "ꭳ": "ꭳ",
+       "ꭴ": "ꭴ",
+       "ꭵ": "ꭵ",
+       "ꭶ": "ꭶ",
+       "ꭷ": "ꭷ",
+       "ꭸ": "ꭸ",
+       "ꭹ": "ꭹ",
+       "ꭺ": "ꭺ",
+       "ꭻ": "ꭻ",
+       "ꭼ": "ꭼ",
+       "ꭽ": "ꭽ",
+       "ꭾ": "ꭾ",
+       "ꭿ": "ꭿ",
+       "ꮀ": "ꮀ",
+       "ꮁ": "ꮁ",
+       "ꮂ": "ꮂ",
+       "ꮃ": "ꮃ",
+       "ꮄ": "ꮄ",
+       "ꮅ": "ꮅ",
+       "ꮆ": "ꮆ",
+       "ꮇ": "ꮇ",
+       "ꮈ": "ꮈ",
+       "ꮉ": "ꮉ",
+       "ꮊ": "ꮊ",
+       "ꮋ": "ꮋ",
+       "ꮌ": "ꮌ",
+       "ꮍ": "ꮍ",
+       "ꮎ": "ꮎ",
+       "ꮏ": "ꮏ",
+       "ꮐ": "ꮐ",
+       "ꮑ": "ꮑ",
+       "ꮒ": "ꮒ",
+       "ꮓ": "ꮓ",
+       "ꮔ": "ꮔ",
+       "ꮕ": "ꮕ",
+       "ꮖ": "ꮖ",
+       "ꮗ": "ꮗ",
+       "ꮘ": "ꮘ",
+       "ꮙ": "ꮙ",
+       "ꮚ": "ꮚ",
+       "ꮛ": "ꮛ",
+       "ꮜ": "ꮜ",
+       "ꮝ": "ꮝ",
+       "ꮞ": "ꮞ",
+       "ꮟ": "ꮟ",
+       "ꮠ": "ꮠ",
+       "ꮡ": "ꮡ",
+       "ꮢ": "ꮢ",
+       "ꮣ": "ꮣ",
+       "ꮤ": "ꮤ",
+       "ꮥ": "ꮥ",
+       "ꮦ": "ꮦ",
+       "ꮧ": "ꮧ",
+       "ꮨ": "ꮨ",
+       "ꮩ": "ꮩ",
+       "ꮪ": "ꮪ",
+       "ꮫ": "ꮫ",
+       "ꮬ": "ꮬ",
+       "ꮭ": "ꮭ",
+       "ꮮ": "ꮮ",
+       "ꮯ": "ꮯ",
+       "ꮰ": "ꮰ",
+       "ꮱ": "ꮱ",
+       "ꮲ": "ꮲ",
+       "ꮳ": "ꮳ",
+       "ꮴ": "ꮴ",
+       "ꮵ": "ꮵ",
+       "ꮶ": "ꮶ",
+       "ꮷ": "ꮷ",
+       "ꮸ": "ꮸ",
+       "ꮹ": "ꮹ",
+       "ꮺ": "ꮺ",
+       "ꮻ": "ꮻ",
+       "ꮼ": "ꮼ",
+       "ꮽ": "ꮽ",
+       "ꮾ": "ꮾ",
+       "ꮿ": "ꮿ",
        "ff": "ff",
        "fi": "fi",
        "fl": "fl",
        "ﬔ": "ﬔ",
        "ﬕ": "ﬕ",
        "ﬖ": "ﬖ",
-       "ﬗ": "ﬗ"
+       "ﬗ": "ﬗ",
+       "𐑎": "𐑎",
+       "𐑏": "𐑏",
+       "𐓘": "𐓘",
+       "𐓙": "𐓙",
+       "𐓚": "𐓚",
+       "𐓛": "𐓛",
+       "𐓜": "𐓜",
+       "𐓝": "𐓝",
+       "𐓞": "𐓞",
+       "𐓟": "𐓟",
+       "𐓠": "𐓠",
+       "𐓡": "𐓡",
+       "𐓢": "𐓢",
+       "𐓣": "𐓣",
+       "𐓤": "𐓤",
+       "𐓥": "𐓥",
+       "𐓦": "𐓦",
+       "𐓧": "𐓧",
+       "𐓨": "𐓨",
+       "𐓩": "𐓩",
+       "𐓪": "𐓪",
+       "𐓫": "𐓫",
+       "𐓬": "𐓬",
+       "𐓭": "𐓭",
+       "𐓮": "𐓮",
+       "𐓯": "𐓯",
+       "𐓰": "𐓰",
+       "𐓱": "𐓱",
+       "𐓲": "𐓲",
+       "𐓳": "𐓳",
+       "𐓴": "𐓴",
+       "𐓵": "𐓵",
+       "𐓶": "𐓶",
+       "𐓷": "𐓷",
+       "𐓸": "𐓸",
+       "𐓹": "𐓹",
+       "𐓺": "𐓺",
+       "𐓻": "𐓻",
+       "𐳀": "𐳀",
+       "𐳁": "𐳁",
+       "𐳂": "𐳂",
+       "𐳃": "𐳃",
+       "𐳄": "𐳄",
+       "𐳅": "𐳅",
+       "𐳆": "𐳆",
+       "𐳇": "𐳇",
+       "𐳈": "𐳈",
+       "𐳉": "𐳉",
+       "𐳊": "𐳊",
+       "𐳋": "𐳋",
+       "𐳌": "𐳌",
+       "𐳍": "𐳍",
+       "𐳎": "𐳎",
+       "𐳏": "𐳏",
+       "𐳐": "𐳐",
+       "𐳑": "𐳑",
+       "𐳒": "𐳒",
+       "𐳓": "𐳓",
+       "𐳔": "𐳔",
+       "𐳕": "𐳕",
+       "𐳖": "𐳖",
+       "𐳗": "𐳗",
+       "𐳘": "𐳘",
+       "𐳙": "𐳙",
+       "𐳚": "𐳚",
+       "𐳛": "𐳛",
+       "𐳜": "𐳜",
+       "𐳝": "𐳝",
+       "𐳞": "𐳞",
+       "𐳟": "𐳟",
+       "𐳠": "𐳠",
+       "𐳡": "𐳡",
+       "𐳢": "𐳢",
+       "𐳣": "𐳣",
+       "𐳤": "𐳤",
+       "𐳥": "𐳥",
+       "𐳦": "𐳦",
+       "𐳧": "𐳧",
+       "𐳨": "𐳨",
+       "𐳩": "𐳩",
+       "𐳪": "𐳪",
+       "𐳫": "𐳫",
+       "𐳬": "𐳬",
+       "𐳭": "𐳭",
+       "𐳮": "𐳮",
+       "𐳯": "𐳯",
+       "𐳰": "𐳰",
+       "𐳱": "𐳱",
+       "𐳲": "𐳲",
+       "𑣀": "𑣀",
+       "𑣁": "𑣁",
+       "𑣂": "𑣂",
+       "𑣃": "𑣃",
+       "𑣄": "𑣄",
+       "𑣅": "𑣅",
+       "𑣆": "𑣆",
+       "𑣇": "𑣇",
+       "𑣈": "𑣈",
+       "𑣉": "𑣉",
+       "𑣊": "𑣊",
+       "𑣋": "𑣋",
+       "𑣌": "𑣌",
+       "𑣍": "𑣍",
+       "𑣎": "𑣎",
+       "𑣏": "𑣏",
+       "𑣐": "𑣐",
+       "𑣑": "𑣑",
+       "𑣒": "𑣒",
+       "𑣓": "𑣓",
+       "𑣔": "𑣔",
+       "𑣕": "𑣕",
+       "𑣖": "𑣖",
+       "𑣗": "𑣗",
+       "𑣘": "𑣘",
+       "𑣙": "𑣙",
+       "𑣚": "𑣚",
+       "𑣛": "𑣛",
+       "𑣜": "𑣜",
+       "𑣝": "𑣝",
+       "𑣞": "𑣞",
+       "𑣟": "𑣟",
+       "𖹠": "𖹠",
+       "𖹡": "𖹡",
+       "𖹢": "𖹢",
+       "𖹣": "𖹣",
+       "𖹤": "𖹤",
+       "𖹥": "𖹥",
+       "𖹦": "𖹦",
+       "𖹧": "𖹧",
+       "𖹨": "𖹨",
+       "𖹩": "𖹩",
+       "𖹪": "𖹪",
+       "𖹫": "𖹫",
+       "𖹬": "𖹬",
+       "𖹭": "𖹭",
+       "𖹮": "𖹮",
+       "𖹯": "𖹯",
+       "𖹰": "𖹰",
+       "𖹱": "𖹱",
+       "𖹲": "𖹲",
+       "𖹳": "𖹳",
+       "𖹴": "𖹴",
+       "𖹵": "𖹵",
+       "𖹶": "𖹶",
+       "𖹷": "𖹷",
+       "𖹸": "𖹸",
+       "𖹹": "𖹹",
+       "𖹺": "𖹺",
+       "𖹻": "𖹻",
+       "𖹼": "𖹼",
+       "𖹽": "𖹽",
+       "𖹾": "𖹾",
+       "𖹿": "𖹿",
+       "𞤢": "𞤢",
+       "𞤣": "𞤣",
+       "𞤤": "𞤤",
+       "𞤥": "𞤥",
+       "𞤦": "𞤦",
+       "𞤧": "𞤧",
+       "𞤨": "𞤨",
+       "𞤩": "𞤩",
+       "𞤪": "𞤪",
+       "𞤫": "𞤫",
+       "𞤬": "𞤬",
+       "𞤭": "𞤭",
+       "𞤮": "𞤮",
+       "𞤯": "𞤯",
+       "𞤰": "𞤰",
+       "𞤱": "𞤱",
+       "𞤲": "𞤲",
+       "𞤳": "𞤳",
+       "𞤴": "𞤴",
+       "𞤵": "𞤵",
+       "𞤶": "𞤶",
+       "𞤷": "𞤷",
+       "𞤸": "𞤸",
+       "𞤹": "𞤹",
+       "𞤺": "𞤺",
+       "𞤻": "𞤻",
+       "𞤼": "𞤼",
+       "𞤽": "𞤽",
+       "𞤾": "𞤾",
+       "𞤿": "𞤿",
+       "𞥀": "𞥀",
+       "𞥁": "𞥁",
+       "𞥂": "𞥂",
+       "𞥃": "𞥃"
 }
index 33207d4..473635a 100644 (file)
@@ -3,14 +3,6 @@
        // FIXME: mw.htmlform.Element also sets this to empty object
        mw.htmlform = {};
 
-       function debounce( delay, callback ) {
-               var timeout;
-               return function () {
-                       clearTimeout( timeout );
-                       timeout = setTimeout( Function.prototype.apply.bind( callback, this, arguments ), delay );
-               };
-       }
-
        /**
         * @class mw.htmlform.Checker
         */
@@ -60,7 +52,7 @@
                if ( $extraElements ) {
                        $e = $e.add( $extraElements );
                }
-               $e.on( events, debounce( 1000, this.validate.bind( this ) ) );
+               $e.on( events, mw.util.debounce( 1000, this.validate.bind( this ) ) );
 
                return this;
        };
index 3b99696..2c88bdc 100644 (file)
@@ -354,7 +354,7 @@ a.new {
        font-weight: bold;
 }
 
-/* Error, warning and success messages */
+/* Error, warning, success and neutral messages */
 .error,
 .warning,
 .success {
@@ -373,41 +373,46 @@ a.new {
        color: #14866d;
 }
 
+.messagebox,
 .errorbox,
 .warningbox,
 .successbox {
+       color: #000;
+       display: inline-block;
+       margin-bottom: 1em;
        border: 1px solid;
        padding: 0.5em 1em;
-       margin-bottom: 1em;
-       display: inline-block;
 }
 
+.messagebox h2,
 .errorbox h2,
 .warningbox h2,
 .successbox h2 {
        color: inherit;
-       font-size: 1em;
-       font-weight: bold;
        display: inline;
        margin: 0 0.5em 0 0;
        border: 0;
+       font-size: 1em;
+       font-weight: bold;
+}
+
+.messagebox {
+       background-color: #eaecf0;
+       border-color: #a2a9b1;
 }
 
 .errorbox {
        background-color: #fee7e6;
-       color: #000;
        border-color: #d33;
 }
 
 .warningbox {
        background-color: #fef6e7;
-       color: #000;
        border-color: #fc3;
 }
 
 .successbox {
        background-color: #d5fdf4;
-       color: #000;
        border-color: #14866d;
 }
 
index 6342011..8521664 100644 (file)
@@ -13,8 +13,7 @@ require( './jquery.accessKeyLabel.js' );
  * @return {string} Encoded string
  */
 function rawurlencode( str ) {
-       str = String( str );
-       return encodeURIComponent( str )
+       return encodeURIComponent( String( str ) )
                .replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' )
                .replace( /\)/g, '%29' ).replace( /\*/g, '%2A' ).replace( /~/g, '%7E' );
 }
@@ -59,33 +58,50 @@ util = {
        rawurlencode: rawurlencode,
 
        /**
-        * Encode string into HTML id compatible form suitable for use in HTML
-        * Analog to PHP Sanitizer::escapeIdForAttribute()
+        * Encode a string as CSS id, for use as HTML id attribute value.
         *
-        * @since 1.30
+        * Analog to `Sanitizer::escapeIdForAttribute()` in PHP.
         *
+        * @since 1.30
         * @param {string} str String to encode
         * @return {string} Encoded string
         */
        escapeIdForAttribute: function ( str ) {
-               var mode = config.FragmentMode[ 0 ];
-
-               return escapeIdInternal( str, mode );
+               return escapeIdInternal( str, config.FragmentMode[ 0 ] );
        },
 
        /**
-        * Encode string into HTML id compatible form suitable for use in links
-        * Analog to PHP Sanitizer::escapeIdForLink()
+        * Encode a string as URL fragment, for use as HTML anchor link.
         *
-        * @since 1.30
+        * Analog to `Sanitizer::escapeIdForLink()` in PHP.
         *
+        * @since 1.30
         * @param {string} str String to encode
         * @return {string} Encoded string
         */
        escapeIdForLink: function ( str ) {
-               var mode = config.FragmentMode[ 0 ];
+               return escapeIdInternal( str, config.FragmentMode[ 0 ] );
+       },
 
-               return escapeIdInternal( str, mode );
+       /**
+        * Return a wrapper function that is debounced for the given duration.
+        *
+        * When it is first called, a timeout is scheduled. If before the timer
+        * is reached the wrapper is called again, it gets rescheduled for the
+        * same duration from now until it stops being called. The original function
+        * is called from the "tail" of such chain, with the last set of arguments.
+        *
+        * @since 1.34
+        * @param {number} delay Time in milliseconds
+        * @param {Function} callback
+        * @return {Function}
+        */
+       debounce: function ( delay, callback ) {
+               var timeout;
+               return function () {
+                       clearTimeout( timeout );
+                       timeout = setTimeout( Function.prototype.apply.bind( callback, this, arguments ), delay );
+               };
        },
 
        /**
@@ -126,16 +142,15 @@ util = {
         * @return {string} Url of the page with name of `pageName`
         */
        getUrl: function ( pageName, params ) {
-               var titleFragmentStart, url, query,
-                       fragment = '',
+               var fragmentIdx, url, query, fragment,
                        title = typeof pageName === 'string' ? pageName : mw.config.get( 'wgPageName' );
 
                // Find any fragment
-               titleFragmentStart = title.indexOf( '#' );
-               if ( titleFragmentStart !== -1 ) {
-                       fragment = title.slice( titleFragmentStart + 1 );
+               fragmentIdx = title.indexOf( '#' );
+               if ( fragmentIdx !== -1 ) {
+                       fragment = title.slice( fragmentIdx + 1 );
                        // Exclude the fragment from the page name
-                       title = title.slice( 0, titleFragmentStart );
+                       title = title.slice( 0, fragmentIdx );
                }
 
                // Produce query string
@@ -152,7 +167,7 @@ util = {
                }
 
                // Append the encoded fragment
-               if ( fragment.length ) {
+               if ( fragment && fragment.length ) {
                        url += '#' + util.escapeIdForLink( fragment );
                }
 
@@ -160,16 +175,14 @@ util = {
        },
 
        /**
-        * Get address to a script in the wiki root.
-        * For index.php use `mw.config.get( 'wgScript' )`.
+        * Get URL to a MediaWiki entry point.
         *
         * @since 1.18
-        * @param {string} str Name of script (e.g. 'api'), defaults to 'index'
-        * @return {string} Address to script (e.g. '/w/api.php' )
+        * @param {string} [str="index"] Name of MW entry point (e.g. 'index' or 'api')
+        * @return {string} URL to the script file (e.g. '/w/api.php' )
         */
        wikiScript: function ( str ) {
-               str = str || 'index';
-               if ( str === 'index' ) {
+               if ( !str || str === 'index' ) {
                        return mw.config.get( 'wgScript' );
                } else if ( str === 'load' ) {
                        return config.LoadScript;
@@ -195,7 +208,7 @@ util = {
         */
        addCSS: function ( text ) {
                var s = mw.loader.addStyleTag( text );
-               return s.sheet || s.styleSheet || s;
+               return s.sheet;
        },
 
        /**
@@ -440,15 +453,15 @@ util = {
         * @return {boolean}
         */
        isIPv4Address: function ( address, allowBlock ) {
-               var block, RE_IP_BYTE, RE_IP_ADD;
+               var block,
+                       RE_IP_BYTE = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])',
+                       RE_IP_ADD = '(?:' + RE_IP_BYTE + '\\.){3}' + RE_IP_BYTE;
 
                if ( typeof address !== 'string' ) {
                        return false;
                }
 
                block = allowBlock ? '(?:\\/(?:3[0-2]|[12]?\\d))?' : '';
-               RE_IP_BYTE = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])';
-               RE_IP_ADD = '(?:' + RE_IP_BYTE + '\\.){3}' + RE_IP_BYTE;
 
                return ( new RegExp( '^' + RE_IP_ADD + block + '$' ).test( address ) );
        },
@@ -533,6 +546,11 @@ util = {
        }
 };
 
+// Backwards-compatible alias for mediawiki.RegExp module.
+// @deprecated since 1.34
+mw.RegExp = {};
+mw.log.deprecate( mw.RegExp, 'escape', util.escapeRegExp, 'Use mw.util.escapeRegExp() instead.', 'mw.RegExp.escape' );
+
 // Not allowed outside unit tests
 if ( window.QUnit ) {
        util.setOptionsForTest = function ( opts ) {
index 3ac532e..f647f91 100644 (file)
--- a/rest.php
+++ b/rest.php
@@ -23,6 +23,9 @@
 
 use MediaWiki\Rest\EntryPoint;
 
+define( 'MW_REST_API', true );
+define( 'MW_ENTRY_POINT', 'rest' );
+
 require __DIR__ . '/includes/WebStart.php';
 
 EntryPoint::main();
index c8b8ef9..91c3d40 100644 (file)
@@ -1246,8 +1246,6 @@ class ParserTestRunner {
         * @return array
         */
        private function listTables() {
-               global $wgActorTableSchemaMigrationStage;
-
                $tables = [ 'user', 'user_properties', 'user_former_groups', 'page', 'page_restrictions',
                        'protected_titles', 'revision', 'ip_changes', 'text', 'pagelinks', 'imagelinks',
                        'categorylinks', 'templatelinks', 'externallinks', 'langlinks', 'iwlinks',
@@ -1256,15 +1254,9 @@ class ParserTestRunner {
                        'querycache', 'objectcache', 'job', 'l10n_cache', 'redirect', 'querycachetwo',
                        'archive', 'user_groups', 'page_props', 'category',
                        'slots', 'content', 'slot_roles', 'content_models',
-                       'comment', 'revision_comment_temp',
+                       'comment', 'revision_comment_temp', 'actor', 'revision_actor_temp',
                ];
 
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                       // The new tables for actors are in use
-                       $tables[] = 'actor';
-                       $tables[] = 'revision_actor_temp';
-               }
-
                if ( in_array( $this->db->getType(), [ 'mysql', 'sqlite' ] ) ) {
                        array_push( $tables, 'searchindex' );
                }
index b738312..ecd5c05 100644 (file)
@@ -1832,11 +1832,16 @@ abstract class MediaWikiIntegrationTestCase extends PHPUnit\Framework\TestCase {
                                'revision_actor_temp', 'slots', 'content', 'content_models', 'slot_roles',
                                'change_tag',
                        ];
+                       $loggingTables = [
+                               'logging', 'log_search', 'change_tag',
+                       ];
                        $coreDBDataTables = array_merge( $userTables, $pageTables );
 
-                       // If any of the user or page tables were marked as used, we should clear all of them.
+                       // some groups of tables are connected such that if any is used, all should be cleared
+                       $extraTables = [];
                        if ( array_intersect( $tablesUsed, $userTables ) ) {
-                               $tablesUsed = array_unique( array_merge( $tablesUsed, $userTables ) );
+                               $extraTables[] = $userTables;
+
                                TestUserRegistry::clear();
 
                                // Reset $wgUser, which is probably 127.0.0.1, as its loaded data is probably not valid
@@ -1846,7 +1851,13 @@ abstract class MediaWikiIntegrationTestCase extends PHPUnit\Framework\TestCase {
                                $wgUser->clearInstanceCache( $wgUser->mFrom );
                        }
                        if ( array_intersect( $tablesUsed, $pageTables ) ) {
-                               $tablesUsed = array_unique( array_merge( $tablesUsed, $pageTables ) );
+                               $extraTables[] = $pageTables;
+                       }
+                       if ( array_intersect( $tablesUsed, $loggingTables ) ) {
+                               $extraTables[] = $loggingTables;
+                       }
+                       if ( $extraTables !== [] ) {
+                               $tablesUsed = array_unique( array_merge( $tablesUsed, ...$extraTables ) );
                        }
 
                        // Postgres uses mwuser/pagecontent
diff --git a/tests/phpunit/data/media/jpeg-xmp-nullchar.jpg b/tests/phpunit/data/media/jpeg-xmp-nullchar.jpg
new file mode 100644 (file)
index 0000000..76ae2b4
Binary files /dev/null and b/tests/phpunit/data/media/jpeg-xmp-nullchar.jpg differ
index 46c0c42..a82b697 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 use MediaWiki\User\UserIdentity;
-use MediaWiki\MediaWikiServices;
+use Wikimedia\ScopedCallback;
 use Wikimedia\TestingAccessWrapper;
 
 /**
@@ -10,14 +10,60 @@ use Wikimedia\TestingAccessWrapper;
  */
 class ActorMigrationTest extends MediaWikiLangTestCase {
 
+       protected $resetActorMigration = null;
+       protected static $amId = 0;
+
        protected $tablesUsed = [
-               'revision',
-               'revision_actor_temp',
-               'ipblocks',
-               'recentchanges',
                'actor',
        ];
 
+       protected function setUp() {
+               parent::setUp();
+
+               $w = TestingAccessWrapper::newFromClass( ActorMigration::class );
+               $data = [
+                       'tempTables' => $w->tempTables,
+                       'formerTempTables' => $w->formerTempTables,
+                       'deprecated' => $w->deprecated,
+                       'removed' => $w->removed,
+                       'specialFields' => $w->specialFields,
+               ];
+               $this->resetActorMigration = new ScopedCallback( function ( $w, $data ) {
+                       foreach ( $data as $k => $v ) {
+                               $w->$k = $v;
+                       }
+               }, [ $w, $data ] );
+
+               $w->tempTables = [
+                       'am2_user' => [
+                               'table' => 'actormigration2_temp',
+                               'pk' => 'am2t_id',
+                               'field' => 'am2t_actor',
+                               'joinPK' => 'am2_id',
+                               'extra' => [],
+                       ]
+               ];
+               $w->specialFields = [
+                       'am3_xxx' => [ 'am3_xxx_text', 'am3_xxx_actor' ],
+               ];
+       }
+
+       protected function tearDown() {
+               parent::tearDown();
+               ScopedCallback::consume( $this->resetActorMigration );
+       }
+
+       protected function getSchemaOverrides( IMaintainableDatabase $db ) {
+               return [
+                       'scripts' => [
+                               __DIR__ . '/ActorMigrationTest.sql',
+                       ],
+                       'drop' => [],
+                       'create' => [ 'actormigration1', 'actormigration2', 'actormigration2_temp', 'actormigration3' ],
+                       'alter' => [],
+               ];
+       }
+
        /**
         * @dataProvider provideConstructor
         * @param int $stage
@@ -80,156 +126,156 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
        public static function provideGetJoin() {
                return [
                        'Simple table, old' => [
-                               SCHEMA_COMPAT_OLD, 'rc_user', [
+                               SCHEMA_COMPAT_OLD, 'am1_user', [
                                        'tables' => [],
                                        'fields' => [
-                                               'rc_user' => 'rc_user',
-                                               'rc_user_text' => 'rc_user_text',
-                                               'rc_actor' => 'NULL',
+                                               'am1_user' => 'am1_user',
+                                               'am1_user_text' => 'am1_user_text',
+                                               'am1_actor' => 'NULL',
                                        ],
                                        'joins' => [],
                                ],
                        ],
                        'Simple table, read-old' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'rc_user', [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'am1_user', [
                                        'tables' => [],
                                        'fields' => [
-                                               'rc_user' => 'rc_user',
-                                               'rc_user_text' => 'rc_user_text',
-                                               'rc_actor' => 'NULL',
+                                               'am1_user' => 'am1_user',
+                                               'am1_user_text' => 'am1_user_text',
+                                               'am1_actor' => 'NULL',
                                        ],
                                        'joins' => [],
                                ],
                        ],
                        'Simple table, read-new' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'rc_user', [
-                                       'tables' => [ 'actor_rc_user' => 'actor' ],
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'am1_user', [
+                                       'tables' => [ 'actor_am1_user' => 'actor' ],
                                        'fields' => [
-                                               'rc_user' => 'actor_rc_user.actor_user',
-                                               'rc_user_text' => 'actor_rc_user.actor_name',
-                                               'rc_actor' => 'rc_actor',
+                                               'am1_user' => 'actor_am1_user.actor_user',
+                                               'am1_user_text' => 'actor_am1_user.actor_name',
+                                               'am1_actor' => 'am1_actor',
                                        ],
                                        'joins' => [
-                                               'actor_rc_user' => [ 'JOIN', 'actor_rc_user.actor_id = rc_actor' ],
+                                               'actor_am1_user' => [ 'JOIN', 'actor_am1_user.actor_id = am1_actor' ],
                                        ],
                                ],
                        ],
                        'Simple table, new' => [
-                               SCHEMA_COMPAT_NEW, 'rc_user', [
-                                       'tables' => [ 'actor_rc_user' => 'actor' ],
+                               SCHEMA_COMPAT_NEW, 'am1_user', [
+                                       'tables' => [ 'actor_am1_user' => 'actor' ],
                                        'fields' => [
-                                               'rc_user' => 'actor_rc_user.actor_user',
-                                               'rc_user_text' => 'actor_rc_user.actor_name',
-                                               'rc_actor' => 'rc_actor',
+                                               'am1_user' => 'actor_am1_user.actor_user',
+                                               'am1_user_text' => 'actor_am1_user.actor_name',
+                                               'am1_actor' => 'am1_actor',
                                        ],
                                        'joins' => [
-                                               'actor_rc_user' => [ 'JOIN', 'actor_rc_user.actor_id = rc_actor' ],
+                                               'actor_am1_user' => [ 'JOIN', 'actor_am1_user.actor_id = am1_actor' ],
                                        ],
                                ],
                        ],
 
-                       'ipblocks, old' => [
-                               SCHEMA_COMPAT_OLD, 'ipb_by', [
+                       'Special name, old' => [
+                               SCHEMA_COMPAT_OLD, 'am3_xxx', [
                                        'tables' => [],
                                        'fields' => [
-                                               'ipb_by' => 'ipb_by',
-                                               'ipb_by_text' => 'ipb_by_text',
-                                               'ipb_by_actor' => 'NULL',
+                                               'am3_xxx' => 'am3_xxx',
+                                               'am3_xxx_text' => 'am3_xxx_text',
+                                               'am3_xxx_actor' => 'NULL',
                                        ],
                                        'joins' => [],
                                ],
                        ],
-                       'ipblocks, read-old' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'ipb_by', [
+                       'Special name, read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'am3_xxx', [
                                        'tables' => [],
                                        'fields' => [
-                                               'ipb_by' => 'ipb_by',
-                                               'ipb_by_text' => 'ipb_by_text',
-                                               'ipb_by_actor' => 'NULL',
+                                               'am3_xxx' => 'am3_xxx',
+                                               'am3_xxx_text' => 'am3_xxx_text',
+                                               'am3_xxx_actor' => 'NULL',
                                        ],
                                        'joins' => [],
                                ],
                        ],
-                       'ipblocks, read-new' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'ipb_by', [
-                                       'tables' => [ 'actor_ipb_by' => 'actor' ],
+                       'Special name, read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'am3_xxx', [
+                                       'tables' => [ 'actor_am3_xxx' => 'actor' ],
                                        'fields' => [
-                                               'ipb_by' => 'actor_ipb_by.actor_user',
-                                               'ipb_by_text' => 'actor_ipb_by.actor_name',
-                                               'ipb_by_actor' => 'ipb_by_actor',
+                                               'am3_xxx' => 'actor_am3_xxx.actor_user',
+                                               'am3_xxx_text' => 'actor_am3_xxx.actor_name',
+                                               'am3_xxx_actor' => 'am3_xxx_actor',
                                        ],
                                        'joins' => [
-                                               'actor_ipb_by' => [ 'JOIN', 'actor_ipb_by.actor_id = ipb_by_actor' ],
+                                               'actor_am3_xxx' => [ 'JOIN', 'actor_am3_xxx.actor_id = am3_xxx_actor' ],
                                        ],
                                ],
                        ],
-                       'ipblocks, new' => [
-                               SCHEMA_COMPAT_NEW, 'ipb_by', [
-                                       'tables' => [ 'actor_ipb_by' => 'actor' ],
+                       'Special name, new' => [
+                               SCHEMA_COMPAT_NEW, 'am3_xxx', [
+                                       'tables' => [ 'actor_am3_xxx' => 'actor' ],
                                        'fields' => [
-                                               'ipb_by' => 'actor_ipb_by.actor_user',
-                                               'ipb_by_text' => 'actor_ipb_by.actor_name',
-                                               'ipb_by_actor' => 'ipb_by_actor',
+                                               'am3_xxx' => 'actor_am3_xxx.actor_user',
+                                               'am3_xxx_text' => 'actor_am3_xxx.actor_name',
+                                               'am3_xxx_actor' => 'am3_xxx_actor',
                                        ],
                                        'joins' => [
-                                               'actor_ipb_by' => [ 'JOIN', 'actor_ipb_by.actor_id = ipb_by_actor' ],
+                                               'actor_am3_xxx' => [ 'JOIN', 'actor_am3_xxx.actor_id = am3_xxx_actor' ],
                                        ],
                                ],
                        ],
 
-                       'Revision, old' => [
-                               SCHEMA_COMPAT_OLD, 'rev_user', [
+                       'Temp table, old' => [
+                               SCHEMA_COMPAT_OLD, 'am2_user', [
                                        'tables' => [],
                                        'fields' => [
-                                               'rev_user' => 'rev_user',
-                                               'rev_user_text' => 'rev_user_text',
-                                               'rev_actor' => 'NULL',
+                                               'am2_user' => 'am2_user',
+                                               'am2_user_text' => 'am2_user_text',
+                                               'am2_actor' => 'NULL',
                                        ],
                                        'joins' => [],
                                ],
                        ],
-                       'Revision, read-old' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'rev_user', [
+                       'Temp table, read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'am2_user', [
                                        'tables' => [],
                                        'fields' => [
-                                               'rev_user' => 'rev_user',
-                                               'rev_user_text' => 'rev_user_text',
-                                               'rev_actor' => 'NULL',
+                                               'am2_user' => 'am2_user',
+                                               'am2_user_text' => 'am2_user_text',
+                                               'am2_actor' => 'NULL',
                                        ],
                                        'joins' => [],
                                ],
                        ],
-                       'Revision, read-new' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'rev_user', [
+                       'Temp table, read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'am2_user', [
                                        'tables' => [
-                                               'temp_rev_user' => 'revision_actor_temp',
-                                               'actor_rev_user' => 'actor',
+                                               'temp_am2_user' => 'actormigration2_temp',
+                                               'actor_am2_user' => 'actor',
                                        ],
                                        'fields' => [
-                                               'rev_user' => 'actor_rev_user.actor_user',
-                                               'rev_user_text' => 'actor_rev_user.actor_name',
-                                               'rev_actor' => 'temp_rev_user.revactor_actor',
+                                               'am2_user' => 'actor_am2_user.actor_user',
+                                               'am2_user_text' => 'actor_am2_user.actor_name',
+                                               'am2_actor' => 'temp_am2_user.am2t_actor',
                                        ],
                                        'joins' => [
-                                               'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
-                                               'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
+                                               'temp_am2_user' => [ 'JOIN', 'temp_am2_user.am2t_id = am2_id' ],
+                                               'actor_am2_user' => [ 'JOIN', 'actor_am2_user.actor_id = temp_am2_user.am2t_actor' ],
                                        ],
                                ],
                        ],
-                       'Revision, new' => [
-                               SCHEMA_COMPAT_NEW, 'rev_user', [
+                       'Temp table, new' => [
+                               SCHEMA_COMPAT_NEW, 'am2_user', [
                                        'tables' => [
-                                               'temp_rev_user' => 'revision_actor_temp',
-                                               'actor_rev_user' => 'actor',
+                                               'temp_am2_user' => 'actormigration2_temp',
+                                               'actor_am2_user' => 'actor',
                                        ],
                                        'fields' => [
-                                               'rev_user' => 'actor_rev_user.actor_user',
-                                               'rev_user_text' => 'actor_rev_user.actor_name',
-                                               'rev_actor' => 'temp_rev_user.revactor_actor',
+                                               'am2_user' => 'actor_am2_user.actor_user',
+                                               'am2_user_text' => 'actor_am2_user.actor_name',
+                                               'am2_actor' => 'temp_am2_user.am2t_actor',
                                        ],
                                        'joins' => [
-                                               'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
-                                               'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
+                                               'temp_am2_user' => [ 'JOIN', 'temp_am2_user.am2t_id = am2_id' ],
+                                               'actor_am2_user' => [ 'JOIN', 'actor_am2_user.actor_id = temp_am2_user.am2t_actor' ],
                                        ],
                                ],
                        ],
@@ -276,164 +322,164 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
 
                return [
                        'Simple table, old' => [
-                               SCHEMA_COMPAT_OLD, 'rc_user', $genericUser, true, [
+                               SCHEMA_COMPAT_OLD, 'am1_user', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'userid' => "rc_user = '1'" ],
+                                       'orconds' => [ 'userid' => "am1_user = '1'" ],
                                        'joins' => [],
                                ],
                        ],
                        'Simple table, read-old' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'rc_user', $genericUser, true, [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'am1_user', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'userid' => "rc_user = '1'" ],
+                                       'orconds' => [ 'userid' => "am1_user = '1'" ],
                                        'joins' => [],
                                ],
                        ],
                        'Simple table, read-new' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'rc_user', $genericUser, true, [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'am1_user', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'actor' => "rc_actor = '11'" ],
+                                       'orconds' => [ 'actor' => "am1_actor = '11'" ],
                                        'joins' => [],
                                ],
                        ],
                        'Simple table, new' => [
-                               SCHEMA_COMPAT_NEW, 'rc_user', $genericUser, true, [
+                               SCHEMA_COMPAT_NEW, 'am1_user', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'actor' => "rc_actor = '11'" ],
+                                       'orconds' => [ 'actor' => "am1_actor = '11'" ],
                                        'joins' => [],
                                ],
                        ],
 
-                       'ipblocks, old' => [
-                               SCHEMA_COMPAT_OLD, 'ipb_by', $genericUser, true, [
+                       'Special name, old' => [
+                               SCHEMA_COMPAT_OLD, 'am3_xxx', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'userid' => "ipb_by = '1'" ],
+                                       'orconds' => [ 'userid' => "am3_xxx = '1'" ],
                                        'joins' => [],
                                ],
                        ],
-                       'ipblocks, read-old' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'ipb_by', $genericUser, true, [
+                       'Special name, read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'am3_xxx', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'userid' => "ipb_by = '1'" ],
+                                       'orconds' => [ 'userid' => "am3_xxx = '1'" ],
                                        'joins' => [],
                                ],
                        ],
-                       'ipblocks, read-new' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'ipb_by', $genericUser, true, [
+                       'Special name, read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'am3_xxx', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'actor' => "ipb_by_actor = '11'" ],
+                                       'orconds' => [ 'actor' => "am3_xxx_actor = '11'" ],
                                        'joins' => [],
                                ],
                        ],
-                       'ipblocks, new' => [
-                               SCHEMA_COMPAT_NEW, 'ipb_by', $genericUser, true, [
+                       'Special name, new' => [
+                               SCHEMA_COMPAT_NEW, 'am3_xxx', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'actor' => "ipb_by_actor = '11'" ],
+                                       'orconds' => [ 'actor' => "am3_xxx_actor = '11'" ],
                                        'joins' => [],
                                ],
                        ],
 
-                       'Revision, old' => [
-                               SCHEMA_COMPAT_OLD, 'rev_user', $genericUser, true, [
+                       'Temp table, old' => [
+                               SCHEMA_COMPAT_OLD, 'am2_user', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'userid' => "rev_user = '1'" ],
+                                       'orconds' => [ 'userid' => "am2_user = '1'" ],
                                        'joins' => [],
                                ],
                        ],
-                       'Revision, read-old' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'rev_user', $genericUser, true, [
+                       'Temp table, read-old' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'am2_user', $genericUser, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'userid' => "rev_user = '1'" ],
+                                       'orconds' => [ 'userid' => "am2_user = '1'" ],
                                        'joins' => [],
                                ],
                        ],
-                       'Revision, read-new' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'rev_user', $genericUser, true, [
+                       'Temp table, read-new' => [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'am2_user', $genericUser, true, [
                                        'tables' => [
-                                               'temp_rev_user' => 'revision_actor_temp',
+                                               'temp_am2_user' => 'actormigration2_temp',
                                        ],
-                                       'orconds' => [ 'actor' => "temp_rev_user.revactor_actor = '11'" ],
+                                       'orconds' => [ 'actor' => "temp_am2_user.am2t_actor = '11'" ],
                                        'joins' => [
-                                               'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                               'temp_am2_user' => [ 'JOIN', 'temp_am2_user.am2t_id = am2_id' ],
                                        ],
                                ],
                        ],
-                       'Revision, new' => [
-                               SCHEMA_COMPAT_NEW, 'rev_user', $genericUser, true, [
+                       'Temp table, new' => [
+                               SCHEMA_COMPAT_NEW, 'am2_user', $genericUser, true, [
                                        'tables' => [
-                                               'temp_rev_user' => 'revision_actor_temp',
+                                               'temp_am2_user' => 'actormigration2_temp',
                                        ],
-                                       'orconds' => [ 'actor' => "temp_rev_user.revactor_actor = '11'" ],
+                                       'orconds' => [ 'actor' => "temp_am2_user.am2t_actor = '11'" ],
                                        'joins' => [
-                                               'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                               'temp_am2_user' => [ 'JOIN', 'temp_am2_user.am2t_id = am2_id' ],
                                        ],
                                ],
                        ],
 
                        'Multiple users, old' => [
-                               SCHEMA_COMPAT_OLD, 'rc_user', $complicatedUsers, true, [
+                               SCHEMA_COMPAT_OLD, 'am1_user', $complicatedUsers, true, [
                                        'tables' => [],
                                        'orconds' => [
-                                               'userid' => "rc_user IN ('1','2','3') ",
-                                               'username' => "rc_user_text IN ('192.168.12.34','192.168.12.35') "
+                                               'userid' => "am1_user IN ('1','2','3') ",
+                                               'username' => "am1_user_text IN ('192.168.12.34','192.168.12.35') "
                                        ],
                                        'joins' => [],
                                ],
                        ],
                        'Multiple users, read-old' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'rc_user', $complicatedUsers, true, [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'am1_user', $complicatedUsers, true, [
                                        'tables' => [],
                                        'orconds' => [
-                                               'userid' => "rc_user IN ('1','2','3') ",
-                                               'username' => "rc_user_text IN ('192.168.12.34','192.168.12.35') "
+                                               'userid' => "am1_user IN ('1','2','3') ",
+                                               'username' => "am1_user_text IN ('192.168.12.34','192.168.12.35') "
                                        ],
                                        'joins' => [],
                                ],
                        ],
                        'Multiple users, read-new' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'rc_user', $complicatedUsers, true, [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'am1_user', $complicatedUsers, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
+                                       'orconds' => [ 'actor' => "am1_actor IN ('11','12','34') " ],
                                        'joins' => [],
                                ],
                        ],
                        'Multiple users, new' => [
-                               SCHEMA_COMPAT_NEW, 'rc_user', $complicatedUsers, true, [
+                               SCHEMA_COMPAT_NEW, 'am1_user', $complicatedUsers, true, [
                                        'tables' => [],
-                                       'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
+                                       'orconds' => [ 'actor' => "am1_actor IN ('11','12','34') " ],
                                        'joins' => [],
                                ],
                        ],
 
                        'Multiple users, no use ID, old' => [
-                               SCHEMA_COMPAT_OLD, 'rc_user', $complicatedUsers, false, [
+                               SCHEMA_COMPAT_OLD, 'am1_user', $complicatedUsers, false, [
                                        'tables' => [],
                                        'orconds' => [
-                                               'username' => "rc_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
+                                               'username' => "am1_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
                                        ],
                                        'joins' => [],
                                ],
                        ],
                        'Multiple users, read-old' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'rc_user', $complicatedUsers, false, [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD, 'am1_user', $complicatedUsers, false, [
                                        'tables' => [],
                                        'orconds' => [
-                                               'username' => "rc_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
+                                               'username' => "am1_user_text IN ('User1','User2','User3','192.168.12.34','192.168.12.35') "
                                        ],
                                        'joins' => [],
                                ],
                        ],
                        'Multiple users, read-new' => [
-                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'rc_user', $complicatedUsers, false, [
+                               SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW, 'am1_user', $complicatedUsers, false, [
                                        'tables' => [],
-                                       'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
+                                       'orconds' => [ 'actor' => "am1_actor IN ('11','12','34') " ],
                                        'joins' => [],
                                ],
                        ],
                        'Multiple users, new' => [
-                               SCHEMA_COMPAT_NEW, 'rc_user', $complicatedUsers, false, [
+                               SCHEMA_COMPAT_NEW, 'am1_user', $complicatedUsers, false, [
                                        'tables' => [],
-                                       'orconds' => [ 'actor' => "rc_actor IN ('11','12','34') " ],
+                                       'orconds' => [ 'actor' => "am1_actor IN ('11','12','34') " ],
                                        'joins' => [],
                                ],
                        ],
@@ -445,23 +491,14 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
         * @param string $table
         * @param string $key
         * @param string $pk
-        * @param array $extraFields
+        * @param bool $usesTemp
         */
-       public function testInsertRoundTrip( $table, $key, $pk, $extraFields ) {
+       public function testInsertRoundTrip( $table, $key, $pk, $usesTemp ) {
                $u = $this->getTestUser()->getUser();
                $user = $this->getMock( UserIdentity::class );
                $user->method( 'getId' )->willReturn( $u->getId() );
                $user->method( 'getName' )->willReturn( $u->getName() );
-               if ( $u->getActorId( $this->db ) ) {
-                       $user->method( 'getActorId' )->willReturn( $u->getActorId() );
-               } else {
-                       $this->db->insert(
-                               'actor',
-                               [ 'actor_user' => $u->getId(), 'actor_name' => $u->getName() ],
-                               __METHOD__
-                       );
-                       $user->method( 'getActorId' )->willReturn( $this->db->insertId() );
-               }
+               $user->method( 'getActorId' )->willReturn( $u->getActorId( $this->db ) );
 
                $stageNames = [
                        SCHEMA_COMPAT_OLD => 'old',
@@ -494,15 +531,10 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
                ];
 
                $nameKey = $key . '_text';
-               $actorKey = $key === 'ipb_by' ? 'ipb_by_actor' : substr( $key, 0, -5 ) . '_actor';
+               $actorKey = ( $key === 'am3_xxx' ? $key : substr( $key, 0, -5 ) ) . '_actor';
 
                foreach ( $stages as $writeStage => $possibleReadStages ) {
-                       if ( $key === 'ipb_by' ) {
-                               $extraFields['ipb_address'] = __CLASS__ . "#{$stageNames[$writeStage]}";
-                       }
-
                        $w = new ActorMigration( $writeStage );
-                       $usesTemp = $key === 'rev_user';
 
                        if ( $usesTemp ) {
                                list( $fields, $callback ) = $w->getInsertValuesWithTempTable( $this->db, $key, $user );
@@ -527,10 +559,10 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
                                        "new field, stage={$stageNames[$writeStage]}" );
                        }
 
-                       $this->db->insert( $table, $extraFields + $fields, __METHOD__ );
-                       $id = $this->db->insertId();
+                       $id = ++self::$amId;
+                       $this->db->insert( $table, [ $pk => $id ] + $fields, __METHOD__ );
                        if ( $usesTemp ) {
-                               $callback( $id, $extraFields );
+                               $callback( $id, [] );
                        }
 
                        foreach ( $possibleReadStages as $readStage ) {
@@ -560,33 +592,10 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
        }
 
        public static function provideInsertRoundTrip() {
-               $db = wfGetDB( DB_REPLICA ); // for timestamps
-
-               $comment = MediaWikiServices::getInstance()->getCommentStore()
-                       ->createComment( wfGetDB( DB_MASTER ), '' );
-
                return [
-                       'recentchanges' => [ 'recentchanges', 'rc_user', 'rc_id', [
-                               'rc_timestamp' => $db->timestamp(),
-                               'rc_namespace' => 0,
-                               'rc_title' => 'Test',
-                               'rc_this_oldid' => 42,
-                               'rc_last_oldid' => 41,
-                               'rc_source' => 'test',
-                               'rc_comment_id' => $comment->id,
-                       ] ],
-                       'ipblocks' => [ 'ipblocks', 'ipb_by', 'ipb_id', [
-                               'ipb_range_start' => '',
-                               'ipb_range_end' => '',
-                               'ipb_timestamp' => $db->timestamp(),
-                               'ipb_expiry' => $db->getInfinity(),
-                               'ipb_reason_id' => $comment->id,
-                       ] ],
-                       'revision' => [ 'revision', 'rev_user', 'rev_id', [
-                               'rev_page' => 42,
-                               'rev_len' => 0,
-                               'rev_timestamp' => $db->timestamp(),
-                       ] ],
+                       'normal' => [ 'actormigration1', 'am1_user', 'am1_id', false ],
+                       'temp table' => [ 'actormigration2', 'am2_user', 'am2_id', true ],
+                       'special name' => [ 'actormigration3', 'am3_xxx', 'am3_id', false ],
                ];
        }
 
@@ -603,22 +612,22 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
         * @dataProvider provideStages
         * @param int $stage
         * @expectedException InvalidArgumentException
-        * @expectedExceptionMessage Must use getInsertValuesWithTempTable() for rev_user
+        * @expectedExceptionMessage Must use getInsertValuesWithTempTable() for am2_user
         */
        public function testInsertWrong( $stage ) {
                $m = new ActorMigration( $stage );
-               $m->getInsertValues( $this->db, 'rev_user', $this->getTestUser()->getUser() );
+               $m->getInsertValues( $this->db, 'am2_user', $this->getTestUser()->getUser() );
        }
 
        /**
         * @dataProvider provideStages
         * @param int $stage
         * @expectedException InvalidArgumentException
-        * @expectedExceptionMessage Must use getInsertValues() for rc_user
+        * @expectedExceptionMessage Must use getInsertValues() for am1_user
         */
        public function testInsertWithTempTableWrong( $stage ) {
                $m = new ActorMigration( $stage );
-               $m->getInsertValuesWithTempTable( $this->db, 'rc_user', $this->getTestUser()->getUser() );
+               $m->getInsertValuesWithTempTable( $this->db, 'am1_user', $this->getTestUser()->getUser() );
        }
 
        /**
@@ -627,12 +636,12 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
         */
        public function testInsertWithTempTableDeprecated( $stage ) {
                $wrap = TestingAccessWrapper::newFromClass( ActorMigration::class );
-               $wrap->formerTempTables += [ 'rc_user' => '1.30' ];
+               $wrap->formerTempTables += [ 'am1_user' => '1.30' ];
 
-               $this->hideDeprecated( 'ActorMigration::getInsertValuesWithTempTable for rc_user' );
+               $this->hideDeprecated( 'ActorMigration::getInsertValuesWithTempTable for am1_user' );
                $m = new ActorMigration( $stage );
                list( $fields, $callback )
-                       = $m->getInsertValuesWithTempTable( $this->db, 'rc_user', $this->getTestUser()->getUser() );
+                       = $m->getInsertValuesWithTempTable( $this->db, 'am1_user', $this->getTestUser()->getUser() );
                $this->assertTrue( is_callable( $callback ) );
        }
 
@@ -640,12 +649,23 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
         * @dataProvider provideStages
         * @param int $stage
         * @expectedException InvalidArgumentException
-        * @expectedExceptionMessage $extra[rev_timestamp] is not provided
+        * @expectedExceptionMessage $extra[foo_timestamp] is not provided
         */
        public function testInsertWithTempTableCallbackMissingFields( $stage ) {
+               $w = TestingAccessWrapper::newFromClass( ActorMigration::class );
+               $w->tempTables = [
+                       'foo_user' => [
+                               'table' => 'foo_temp',
+                               'pk' => 'footmp_id',
+                               'field' => 'footmp_actor',
+                               'joinPK' => 'foo_id',
+                               'extra' => [ 'footmp_timestamp' => 'foo_timestamp' ],
+                       ],
+               ];
+
                $m = new ActorMigration( $stage );
                list( $fields, $callback )
-                       = $m->getInsertValuesWithTempTable( $this->db, 'rev_user', $this->getTestUser()->getUser() );
+                       = $m->getInsertValuesWithTempTable( $this->db, 'foo_user', $this->getTestUser()->getUser() );
                $callback( 1, [] );
        }
 
@@ -654,41 +674,33 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
         * @param int $stage
         */
        public function testInsertUserIdentity( $stage ) {
-               $this->setMwGlobals( [
-                       // for User::getActorId()
-                       'wgActorTableSchemaMigrationStage' => $stage
-               ] );
-
                $user = $this->getMutableTestUser()->getUser();
                $userIdentity = $this->getMock( UserIdentity::class );
                $userIdentity->method( 'getId' )->willReturn( $user->getId() );
                $userIdentity->method( 'getName' )->willReturn( $user->getName() );
                $userIdentity->method( 'getActorId' )->willReturn( 0 );
 
-               list( $cFields, $cCallback ) = MediaWikiServices::getInstance()->getCommentStore()
-                       ->insertWithTempTable( $this->db, 'rev_comment', '' );
                $m = new ActorMigration( $stage );
                list( $fields, $callback ) =
-                       $m->getInsertValuesWithTempTable( $this->db, 'rev_user', $userIdentity );
-               $extraFields = [
-                       'rev_page' => 42,
-                       'rev_len' => 0,
-                       'rev_timestamp' => $this->db->timestamp(),
-               ] + $cFields;
-               $this->db->insert( 'revision', $extraFields + $fields, __METHOD__ );
-               $id = $this->db->insertId();
-               $callback( $id, $extraFields );
-               $cCallback( $id );
-
-               $qi = $m->getJoin( 'rev_user' );
+                       $m->getInsertValuesWithTempTable( $this->db, 'am2_user', $userIdentity );
+               $id = ++self::$amId;
+               $this->db->insert( 'actormigration2', [ 'am2_id' => $id ] + $fields, __METHOD__ );
+               $callback( $id, [] );
+
+               $qi = $m->getJoin( 'am2_user' );
                $row = $this->db->selectRow(
-                       [ 'revision' ] + $qi['tables'], $qi['fields'], [ 'rev_id' => $id ], __METHOD__, [], $qi['joins']
+                       [ 'actormigration2' ] + $qi['tables'],
+                       $qi['fields'],
+                       [ 'am2_id' => $id ],
+                       __METHOD__,
+                       [],
+                       $qi['joins']
                );
-               $this->assertSame( $user->getId(), (int)$row->rev_user );
-               $this->assertSame( $user->getName(), $row->rev_user_text );
+               $this->assertSame( $user->getId(), (int)$row->am2_user );
+               $this->assertSame( $user->getName(), $row->am2_user_text );
                $this->assertSame(
                        ( $stage & SCHEMA_COMPAT_READ_NEW ) ? $user->getActorId() : 0,
-                       (int)$row->rev_actor
+                       (int)$row->am2_actor
                );
 
                $m = new ActorMigration( $stage );
@@ -736,4 +748,24 @@ class ActorMigrationTest extends MediaWikiLangTestCase {
                ];
        }
 
+       public function testCheckDeprecation() {
+               $wrap = TestingAccessWrapper::newFromClass( ActorMigration::class );
+               $wrap->deprecated += [ 'soft' => null, 'hard' => '1.34' ];
+               $wrap->removed += [ 'gone' => '1.34' ];
+
+               $this->hideDeprecated( 'ActorMigration for \'hard\'' );
+
+               $wrap->checkDeprecation( 'valid' );
+               $wrap->checkDeprecation( 'soft' );
+               $wrap->checkDeprecation( 'hard' );
+               try {
+                       $wrap->checkDeprecation( 'gone' );
+               } catch ( InvalidArgumentException $ex ) {
+                       $this->assertSame(
+                               'Use of ActorMigration for \'gone\' was removed in MediaWiki 1.34',
+                               $ex->getMessage()
+                       );
+               }
+       }
+
 }
diff --git a/tests/phpunit/includes/ActorMigrationTest.sql b/tests/phpunit/includes/ActorMigrationTest.sql
new file mode 100644 (file)
index 0000000..f387dac
--- /dev/null
@@ -0,0 +1,26 @@
+-- These are carefully crafted to work in all five supported databases
+
+CREATE TABLE /*_*/actormigration1 (
+  am1_id integer not null,
+  am1_user integer,
+  am1_user_text varchar(200),
+  am1_actor integer
+);
+
+CREATE TABLE /*_*/actormigration2 (
+  am2_id integer not null,
+  am2_user integer,
+  am2_user_text varchar(200)
+);
+
+CREATE TABLE /*_*/actormigration2_temp (
+  am2t_id integer not null,
+  am2t_actor integer
+);
+
+CREATE TABLE /*_*/actormigration3 (
+  am3_id integer not null,
+  am3_xxx integer,
+  am3_xxx_text varchar(200),
+  am3_xxx_actor integer
+);
index 9665867..7115515 100644 (file)
@@ -4,6 +4,7 @@ namespace MediaWiki\Tests\Revision;
 
 use Content;
 use Language;
+use MediaWiki\MediaWikiServices;
 use MediaWiki\Revision\MutableRevisionRecord;
 use MediaWiki\Revision\MutableRevisionSlots;
 use MediaWiki\Revision\RenderedRevision;
@@ -122,7 +123,9 @@ class RenderedRevisionTest extends MediaWikiTestCase {
                $mock->expects( $this->any() )
                        ->method( 'userCan' )
                        ->willReturnCallback( function ( $perm, User $user ) use ( $mock ) {
-                               return $user->isAllowed( $perm );
+                               return MediaWikiServices::getInstance()
+                                       ->getPermissionManager()
+                                       ->userHasRight( $user, $perm );
                        } );
 
                return $mock;
index 5cc3646..949b664 100644 (file)
@@ -61,32 +61,11 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                ];
        }
 
-       protected function getOldActorQueryFields( $prefix ) {
-               return [
-                       "{$prefix}_user" => "{$prefix}_user",
-                       "{$prefix}_user_text" => "{$prefix}_user_text",
-                       "{$prefix}_actor" => 'NULL',
-               ];
-       }
-
        protected function getNewActorQueryFields( $prefix, $tmp = false ) {
                return [
                        "{$prefix}_user" => "actor_{$prefix}_user.actor_user",
                        "{$prefix}_user_text" => "actor_{$prefix}_user.actor_name",
-                       "{$prefix}_actor" => $tmp ?: "{$prefix}_actor",
-               ];
-       }
-
-       protected function getNewActorJoins( $prefix ) {
-               return [
-                       "temp_{$prefix}_user" => [
-                               "JOIN",
-                               "temp_{$prefix}_user.revactor_{$prefix} = {$prefix}_id",
-                       ],
-                       "actor_{$prefix}_user" => [
-                               "JOIN",
-                               "actor_{$prefix}_user.actor_id = temp_{$prefix}_user.revactor_actor",
-                       ],
+                       "{$prefix}_actor" => $tmp ? "temp_{$prefix}_user.{$prefix}actor_actor" : "{$prefix}_actor",
                ];
        }
 
@@ -125,7 +104,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                yield 'MCR, comment, actor' => [
                        [
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
                        ],
                        [
                                'tables' => [
@@ -150,7 +128,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                'wgContentHandlerUseDB' => true,
                                'wgMultiContentRevisionSchemaMigrationStage'
                                        => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
                        ],
                        [
                                'tables' => [
@@ -175,22 +152,23 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                'wgContentHandlerUseDB' => true,
                                'wgMultiContentRevisionSchemaMigrationStage'
                                        => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
                        ],
                        [
                                'tables' => [
                                        'archive',
+                                       'actor_ar_user' => 'actor',
                                        'comment_ar_comment' => 'comment',
                                ],
                                'fields' => array_merge(
                                        $this->getArchiveQueryFields( true ),
                                        $this->getContentHandlerQueryFields( 'ar' ),
-                                       $this->getOldActorQueryFields( 'ar' ),
+                                       $this->getNewActorQueryFields( 'ar' ),
                                        $this->getNewCommentQueryFields( 'ar' )
                                ),
                                'joins' => [
                                        'comment_ar_comment'
                                                => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
+                                       'actor_ar_user' => [ 'JOIN', 'actor_ar_user.actor_id = ar_actor' ],
                                ],
                        ]
                ];
@@ -198,21 +176,22 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                        [
                                'wgContentHandlerUseDB' => false,
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
                        ],
                        [
                                'tables' => [
                                        'archive',
+                                       'actor_ar_user' => 'actor',
                                        'comment_ar_comment' => 'comment',
                                ],
                                'fields' => array_merge(
                                        $this->getArchiveQueryFields( true ),
-                                       $this->getOldActorQueryFields( 'ar' ),
+                                       $this->getNewActorQueryFields( 'ar' ),
                                        $this->getNewCommentQueryFields( 'ar' )
                                ),
                                'joins' => [
                                        'comment_ar_comment'
                                                => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
+                                       'actor_ar_user' => [ 'JOIN', 'actor_ar_user.actor_id = ar_actor' ],
                                ],
                        ]
                ];
@@ -224,7 +203,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                        [
                                'wgContentHandlerUseDB' => true,
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
                        ],
                        [ 'page', 'user' ],
                        [
@@ -260,6 +238,8 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        ],
                                        'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
                                        'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
                                ],
                        ]
                ];
@@ -268,7 +248,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                'wgContentHandlerUseDB' => true,
                                'wgMultiContentRevisionSchemaMigrationStage'
                                        => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
                        ],
                        [ 'page', 'user' ],
                        [
@@ -288,22 +267,21 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
-                               'joins' => array_merge(
-                                       [
-                                               'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
-                                               'user' => [
-                                                       'LEFT JOIN',
-                                                       [
-                                                               'actor_rev_user.actor_user != 0',
-                                                               'user_id = actor_rev_user.actor_user',
-                                                       ]
-                                               ],
-                                               'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
-                                               'comment_rev_comment'
-                                                       => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                               'joins' => [
+                                       'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
+                                       'user' => [
+                                               'LEFT JOIN',
+                                               [
+                                                       'actor_rev_user.actor_user != 0',
+                                                       'user_id = actor_rev_user.actor_user',
+                                               ]
                                        ],
-                                       $this->getNewActorJoins( 'rev' )
-                               ),
+                                       'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
+                                       'comment_rev_comment'
+                                               => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
+                               ],
                        ]
                ];
                yield 'MCR read-new' => [
@@ -311,7 +289,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                'wgContentHandlerUseDB' => true,
                                'wgMultiContentRevisionSchemaMigrationStage'
                                        => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
                        ],
                        [ 'page', 'user' ],
                        [
@@ -331,22 +308,21 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
-                               'joins' => array_merge(
-                                       [
-                                               'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
-                                               'user' => [
-                                                       'LEFT JOIN',
-                                                       [
-                                                               'actor_rev_user.actor_user != 0',
-                                                               'user_id = actor_rev_user.actor_user'
-                                                       ]
-                                               ],
-                                               'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
-                                               'comment_rev_comment'
-                                                       => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                               'joins' => [
+                                       'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
+                                       'user' => [
+                                               'LEFT JOIN',
+                                               [
+                                                       'actor_rev_user.actor_user != 0',
+                                                       'user_id = actor_rev_user.actor_user'
+                                               ]
                                        ],
-                                       $this->getNewActorJoins( 'rev' )
-                               ),
+                                       'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
+                                       'comment_rev_comment'
+                                               => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
+                               ],
                        ]
                ];
                yield 'MCR write-both/read-old' => [
@@ -354,7 +330,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                'wgContentHandlerUseDB' => true,
                                'wgMultiContentRevisionSchemaMigrationStage'
                                        => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
                        ],
                        [],
                        [
@@ -362,17 +337,21 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'revision',
                                        'temp_rev_comment' => 'revision_comment_temp',
                                        'comment_rev_comment' => 'comment',
+                                       'temp_rev_user' => 'revision_actor_temp',
+                                       'actor_rev_user' => 'actor',
                                ],
                                'fields' => array_merge(
                                        $this->getRevisionQueryFields( true ),
                                        $this->getContentHandlerQueryFields( 'rev' ),
-                                       $this->getOldActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
+                                       $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
                                'joins' => [
                                        'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
                                        'comment_rev_comment'
                                                => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
                                ],
                        ]
                ];
@@ -381,7 +360,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                'wgContentHandlerUseDB' => true,
                                'wgMultiContentRevisionSchemaMigrationStage'
                                        => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
                        ],
                        [ 'page', 'user' ],
                        [
@@ -391,37 +369,38 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'user',
                                        'temp_rev_comment' => 'revision_comment_temp',
                                        'comment_rev_comment' => 'comment',
+                                       'temp_rev_user' => 'revision_actor_temp',
+                                       'actor_rev_user' => 'actor',
                                ],
                                'fields' => array_merge(
                                        $this->getRevisionQueryFields( true ),
                                        $this->getContentHandlerQueryFields( 'rev' ),
                                        $this->getUserQueryFields(),
                                        $this->getPageQueryFields(),
-                                       $this->getOldActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
+                                       $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
-                               'joins' => array_merge(
-                                       [
-                                               'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
-                                               'user' => [
-                                                       'LEFT JOIN',
-                                                       [
-                                                               'rev_user != 0',
-                                                               'user_id = rev_user'
-                                                       ]
-                                               ],
-                                               'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
-                                               'comment_rev_comment'
-                                                       => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
-                                       ]
-                               ),
+                               'joins' => [
+                                       'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
+                                       'user' => [
+                                               'LEFT JOIN',
+                                               [
+                                                       'actor_rev_user.actor_user != 0',
+                                                       'user_id = actor_rev_user.actor_user',
+                                               ]
+                                       ],
+                                       'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
+                                       'comment_rev_comment'
+                                               => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
+                               ],
                        ]
                ];
                yield 'pre-MCR' => [
                        [
                                'wgContentHandlerUseDB' => true,
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
                        ],
                        [],
                        [
@@ -429,17 +408,21 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'revision',
                                        'temp_rev_comment' => 'revision_comment_temp',
                                        'comment_rev_comment' => 'comment',
+                                       'temp_rev_user' => 'revision_actor_temp',
+                                       'actor_rev_user' => 'actor',
                                ],
                                'fields' => array_merge(
                                        $this->getRevisionQueryFields( true ),
                                        $this->getContentHandlerQueryFields( 'rev' ),
-                                       $this->getOldActorQueryFields( 'rev' ),
+                                       $this->getNewActorQueryFields( 'rev', true ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
                                'joins' => [
                                        'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
                                        'comment_rev_comment'
                                                => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
                                ],
                        ]
                ];
@@ -447,7 +430,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                        [
                                'wgContentHandlerUseDB' => true,
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
                        ],
                        [ 'page', 'user' ],
                        [
@@ -455,21 +437,28 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'revision', 'page', 'user',
                                        'temp_rev_comment' => 'revision_comment_temp',
                                        'comment_rev_comment' => 'comment',
+                                       'temp_rev_user' => 'revision_actor_temp',
+                                       'actor_rev_user' => 'actor',
                                ],
                                'fields' => array_merge(
                                        $this->getRevisionQueryFields( true ),
                                        $this->getContentHandlerQueryFields( 'rev' ),
                                        $this->getPageQueryFields(),
                                        $this->getUserQueryFields(),
-                                       $this->getOldActorQueryFields( 'rev' ),
+                                       $this->getNewActorQueryFields( 'rev', true ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
                                'joins' => [
                                        'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
-                                       'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
+                                       'user' => [ 'LEFT JOIN', [
+                                               'actor_rev_user.actor_user != 0',
+                                               'user_id = actor_rev_user.actor_user',
+                                       ] ],
                                        'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
                                        'comment_rev_comment'
                                                => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
                                ],
                        ]
                ];
@@ -477,7 +466,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                        [
                                'wgContentHandlerUseDB' => false,
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
                        ],
                        [],
                        [
@@ -485,16 +473,20 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'revision',
                                        'temp_rev_comment' => 'revision_comment_temp',
                                        'comment_rev_comment' => 'comment',
+                                       'temp_rev_user' => 'revision_actor_temp',
+                                       'actor_rev_user' => 'actor',
                                ],
                                'fields' => array_merge(
                                        $this->getRevisionQueryFields( true ),
-                                       $this->getOldActorQueryFields( 'rev' ),
+                                       $this->getNewActorQueryFields( 'rev', true ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
                                'joins' => [
                                        'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
                                        'comment_rev_comment'
                                                => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
                                ],
                        ],
                ];
@@ -502,7 +494,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                        [
                                'wgContentHandlerUseDB' => false,
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
                        ],
                        [ 'page' ],
                        [
@@ -510,11 +501,13 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'revision', 'page',
                                        'temp_rev_comment' => 'revision_comment_temp',
                                        'comment_rev_comment' => 'comment',
+                                       'temp_rev_user' => 'revision_actor_temp',
+                                       'actor_rev_user' => 'actor',
                                ],
                                'fields' => array_merge(
                                        $this->getRevisionQueryFields( true ),
                                        $this->getPageQueryFields(),
-                                       $this->getOldActorQueryFields( 'rev' ),
+                                       $this->getNewActorQueryFields( 'rev', true ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
                                'joins' => [
@@ -522,6 +515,8 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
                                        'comment_rev_comment'
                                                => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
                                ],
                        ],
                ];
@@ -529,7 +524,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                        [
                                'wgContentHandlerUseDB' => false,
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
                        ],
                        [ 'user' ],
                        [
@@ -537,18 +531,25 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'revision', 'user',
                                        'temp_rev_comment' => 'revision_comment_temp',
                                        'comment_rev_comment' => 'comment',
+                                       'temp_rev_user' => 'revision_actor_temp',
+                                       'actor_rev_user' => 'actor',
                                ],
                                'fields' => array_merge(
                                        $this->getRevisionQueryFields( true ),
                                        $this->getUserQueryFields(),
-                                       $this->getOldActorQueryFields( 'rev' ),
+                                       $this->getNewActorQueryFields( 'rev', true ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
                                'joins' => [
-                                       'user' => [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
+                                       'user' => [ 'LEFT JOIN', [
+                                               'actor_rev_user.actor_user != 0',
+                                               'user_id = actor_rev_user.actor_user',
+                                       ] ],
                                        'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
                                        'comment_rev_comment'
                                                => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
                                ],
                        ],
                ];
@@ -556,7 +557,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                        [
                                'wgContentHandlerUseDB' => false,
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
                        ],
                        [ 'text' ],
                        [
@@ -564,11 +564,13 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'revision', 'text',
                                        'temp_rev_comment' => 'revision_comment_temp',
                                        'comment_rev_comment' => 'comment',
+                                       'temp_rev_user' => 'revision_actor_temp',
+                                       'actor_rev_user' => 'actor',
                                ],
                                'fields' => array_merge(
                                        $this->getRevisionQueryFields( true ),
                                        $this->getTextQueryFields(),
-                                       $this->getOldActorQueryFields( 'rev' ),
+                                       $this->getNewActorQueryFields( 'rev', true ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
                                'joins' => [
@@ -576,6 +578,8 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
                                        'comment_rev_comment'
                                                => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
                                ],
                        ],
                ];
@@ -583,7 +587,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                        [
                                'wgContentHandlerUseDB' => false,
                                'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
                        ],
                        [ 'text', 'page', 'user' ],
                        [
@@ -591,13 +594,15 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'revision', 'page', 'user', 'text',
                                        'temp_rev_comment' => 'revision_comment_temp',
                                        'comment_rev_comment' => 'comment',
+                                       'temp_rev_user' => 'revision_actor_temp',
+                                       'actor_rev_user' => 'actor',
                                ],
                                'fields' => array_merge(
                                        $this->getRevisionQueryFields( true ),
                                        $this->getPageQueryFields(),
                                        $this->getUserQueryFields(),
                                        $this->getTextQueryFields(),
-                                       $this->getOldActorQueryFields( 'rev' ),
+                                       $this->getNewActorQueryFields( 'rev', true ),
                                        $this->getNewCommentQueryFields( 'rev' )
                                ),
                                'joins' => [
@@ -608,8 +613,8 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'user' => [
                                                'LEFT JOIN',
                                                [
-                                                       'rev_user != 0',
-                                                       'user_id = rev_user',
+                                                       'actor_rev_user.actor_user != 0',
+                                                       'user_id = actor_rev_user.actor_user',
                                                ],
                                        ],
                                        'text' => [
@@ -619,6 +624,8 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                                        'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
                                        'comment_rev_comment'
                                                => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
+                                       'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
+                                       'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
                                ],
                        ],
                ];
@@ -848,190 +855,6 @@ class RevisionQueryInfoTest extends MediaWikiTestCase {
                ];
        }
 
-       public function provideSelectFields() {
-               yield 'with model, comment, and actor' => [
-                       [
-                               'wgContentHandlerUseDB' => true,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
-                       ],
-                       'fields' => array_merge(
-                               [
-                                       'rev_id',
-                                       'rev_page',
-                                       'rev_text_id',
-                                       'rev_timestamp',
-                                       'rev_user_text',
-                                       'rev_user',
-                                       'rev_actor' => 'NULL',
-                                       'rev_minor_edit',
-                                       'rev_deleted',
-                                       'rev_len',
-                                       'rev_parent_id',
-                                       'rev_sha1',
-                               ],
-                               $this->getContentHandlerQueryFields( 'rev' ),
-                               [
-                                       'rev_comment_pk' => 'rev_id',
-                               ]
-                       ),
-               ];
-               yield 'no mode, no comment, no actor' => [
-                       [
-                               'wgContentHandlerUseDB' => false,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                       ],
-                       'fields' => array_merge(
-                               [
-                                       'rev_id',
-                                       'rev_page',
-                                       'rev_text_id',
-                                       'rev_timestamp',
-                                       'rev_user_text',
-                                       'rev_user',
-                                       'rev_actor' => 'NULL',
-                                       'rev_minor_edit',
-                                       'rev_deleted',
-                                       'rev_len',
-                                       'rev_parent_id',
-                                       'rev_sha1',
-                                       'rev_comment_pk' => 'rev_id',
-                               ]
-                       ),
-               ];
-       }
-
-       public function provideSelectArchiveFields() {
-               yield 'with model, comment, and actor' => [
-                       [
-                               'wgContentHandlerUseDB' => true,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
-                       ],
-                       'fields' => array_merge(
-                               [
-                                       'ar_id',
-                                       'ar_page_id',
-                                       'ar_rev_id',
-                                       'ar_text_id',
-                                       'ar_timestamp',
-                                       'ar_user_text',
-                                       'ar_user',
-                                       'ar_actor' => 'NULL',
-                                       'ar_minor_edit',
-                                       'ar_deleted',
-                                       'ar_len',
-                                       'ar_parent_id',
-                                       'ar_sha1',
-                               ],
-                               $this->getContentHandlerQueryFields( 'ar' ),
-                               [
-                                       'ar_comment_id' => 'ar_comment_id',
-                               ]
-                       ),
-               ];
-               yield 'no mode, no comment, no actor' => [
-                       [
-                               'wgContentHandlerUseDB' => false,
-                               'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
-                       ],
-                       'fields' => array_merge(
-                               [
-                                       'ar_id',
-                                       'ar_page_id',
-                                       'ar_rev_id',
-                                       'ar_text_id',
-                                       'ar_timestamp',
-                                       'ar_user_text',
-                                       'ar_user',
-                                       'ar_actor' => 'NULL',
-                                       'ar_minor_edit',
-                                       'ar_deleted',
-                                       'ar_len',
-                                       'ar_parent_id',
-                                       'ar_sha1',
-                                       'ar_comment_id' => 'ar_comment_id',
-                               ]
-                       ),
-               ];
-       }
-
-       /**
-        * @dataProvider provideSelectFields
-        * @covers Revision::selectFields
-        */
-       public function testRevisionSelectFields( $migrationStageSettings, $expected ) {
-               $this->setMwGlobals( $migrationStageSettings );
-
-               $this->hideDeprecated( 'Revision::selectFields' );
-               $this->assertArrayEqualsIgnoringIntKeyOrder( $expected, Revision::selectFields() );
-       }
-
-       /**
-        * @dataProvider provideSelectArchiveFields
-        * @covers Revision::selectArchiveFields
-        */
-       public function testRevisionSelectArchiveFields( $migrationStageSettings, $expected ) {
-               $this->setMwGlobals( $migrationStageSettings );
-
-               $this->hideDeprecated( 'Revision::selectArchiveFields' );
-               $this->assertArrayEqualsIgnoringIntKeyOrder( $expected, Revision::selectArchiveFields() );
-       }
-
-       /**
-        * @covers Revision::userJoinCond
-        */
-       public function testRevisionUserJoinCond() {
-               $this->hideDeprecated( 'Revision::userJoinCond' );
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_OLD );
-               $this->assertEquals(
-                       [ 'LEFT JOIN', [ 'rev_user != 0', 'user_id = rev_user' ] ],
-                       Revision::userJoinCond()
-               );
-       }
-
-       /**
-        * @covers Revision::pageJoinCond
-        */
-       public function testRevisionPageJoinCond() {
-               $this->hideDeprecated( 'Revision::pageJoinCond' );
-               $this->assertEquals(
-                       [ 'JOIN', [ 'page_id = rev_page' ] ],
-                       Revision::pageJoinCond()
-               );
-       }
-
-       /**
-        * @covers Revision::selectTextFields
-        */
-       public function testRevisionSelectTextFields() {
-               $this->hideDeprecated( 'Revision::selectTextFields' );
-               $this->assertEquals(
-                       $this->getTextQueryFields(),
-                       Revision::selectTextFields()
-               );
-       }
-
-       /**
-        * @covers Revision::selectPageFields
-        */
-       public function testRevisionSelectPageFields() {
-               $this->hideDeprecated( 'Revision::selectPageFields' );
-               $this->assertEquals(
-                       $this->getPageQueryFields(),
-                       Revision::selectPageFields()
-               );
-       }
-
-       /**
-        * @covers Revision::selectUserFields
-        */
-       public function testRevisionSelectUserFields() {
-               $this->hideDeprecated( 'Revision::selectUserFields' );
-               $this->assertEquals(
-                       $this->getUserQueryFields(),
-                       Revision::selectUserFields()
-               );
-       }
-
        /**
         * @covers Revision::getArchiveQueryInfo
         * @dataProvider provideArchiveQueryInfo
index b0b9ddf..76190e0 100644 (file)
@@ -81,7 +81,6 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase {
                $this->setMwGlobals( [
                        'wgMultiContentRevisionSchemaMigrationStage' => $this->getMcrMigrationStage(),
                        'wgContentHandlerUseDB' => $this->getContentHandlerUseDB(),
-                       'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
                ] );
        }
 
@@ -1791,8 +1790,6 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase {
         * @covers \MediaWiki\Revision\RevisionStore::getKnownCurrentRevision
         */
        public function testGetKnownCurrentRevision_userNameChange() {
-               global $wgActorTableSchemaMigrationStage;
-
                $cache = new WANObjectCache( [ 'cache' => new HashBagOStuff() ] );
                $this->setService( 'MainWANObjectCache', $cache );
 
@@ -1811,11 +1808,9 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase {
                $this->db->update( 'user',
                        [ 'user_name' => $newUserName ],
                        [ 'user_id' => $rev->getUser()->getId() ] );
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                       $this->db->update( 'actor',
-                               [ 'actor_name' => $newUserName ],
-                               [ 'actor_user' => $rev->getUser()->getId() ] );
-               }
+               $this->db->update( 'actor',
+                       [ 'actor_name' => $newUserName ],
+                       [ 'actor_user' => $rev->getUser()->getId() ] );
 
                // Reload the revision and regrab the user name.
                $revAfter = $store->getKnownCurrentRevision( $page->getTitle(), $rev->getId() );
@@ -1864,8 +1859,6 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase {
         * @covers \MediaWiki\Revision\RevisionStore::newRevisionFromRow
         */
        public function testNewRevisionFromRow_userNameChange() {
-               global $wgActorTableSchemaMigrationStage;
-
                $page = $this->getTestPage();
                $text = __METHOD__;
                /** @var Revision $rev */
@@ -1895,11 +1888,9 @@ abstract class RevisionStoreDbTestBase extends MediaWikiTestCase {
                $this->db->update( 'user',
                        [ 'user_name' => $newUserName ],
                        [ 'user_id' => $record->getUser()->getId() ] );
-               if ( $wgActorTableSchemaMigrationStage & SCHEMA_COMPAT_WRITE_NEW ) {
-                       $this->db->update( 'actor',
-                               [ 'actor_name' => $newUserName ],
-                               [ 'actor_user' => $record->getUser()->getId() ] );
-               }
+               $this->db->update( 'actor',
+                       [ 'actor_name' => $newUserName ],
+                       [ 'actor_user' => $record->getUser()->getId() ] );
 
                // Reload the record, passing $fromCache as true to force fresh info from the db,
                // and regrab the user name
index 7b334ee..d41c88f 100644 (file)
@@ -92,7 +92,6 @@ abstract class RevisionDbTestBase extends MediaWikiTestCase {
                $this->setMwGlobals( [
                        'wgMultiContentRevisionSchemaMigrationStage' => $this->getMcrMigrationStage(),
                        'wgContentHandlerUseDB' => $this->getContentHandlerUseDB(),
-                       'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
                ] );
 
                if ( !$this->testPage ) {
index 865bd31..ed4a27f 100644 (file)
@@ -601,7 +601,6 @@ class RevisionTest extends MediaWikiTestCase {
         * @covers Revision::loadFromTitle
         */
        public function testLoadFromTitle() {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
                $title = $this->getMockTitle();
 
                $conditions = [
index 18faeea..82ccb9a 100644 (file)
@@ -768,12 +768,12 @@ class TitleTest extends MediaWikiTestCase {
                $this->assertEquals(
                        false,
                        $title->exists(),
-                       'exists() should rely on link cache unless GAID_FOR_UPDATE is used'
+                       'exists() should rely on link cache unless READ_LATEST is used'
                );
                $this->assertEquals(
                        true,
-                       $title->exists( Title::GAID_FOR_UPDATE ),
-                       'exists() should re-query database when GAID_FOR_UPDATE is used'
+                       $title->exists( Title::READ_LATEST ),
+                       'exists() should re-query database when READ_LATEST is used'
                );
        }
 
index c68954c..d2bbc1f 100644 (file)
@@ -67,7 +67,7 @@ class ApiDeleteTest extends ApiTestCase {
                $jobs->loadParamsAndArgs( null, [ 'quiet' => true ], null );
                $jobs->execute();
 
-               $this->assertFalse( Title::newFromText( $name )->exists( Title::GAID_FOR_UPDATE ) );
+               $this->assertFalse( Title::newFromText( $name )->exists( Title::READ_LATEST ) );
        }
 
        public function testDeleteNonexistent() {
index 1e2135b..3a3f5f1 100644 (file)
@@ -242,11 +242,12 @@ class ApiMainTest extends ApiTestCase {
                $mock->method( 'needsToken' )->willReturn( true );
 
                $api = new ApiMain( new FauxRequest( [ 'action' => 'testmodule' ] ) );
-               $api->getModuleManager()->addModule( 'testmodule', 'action', get_class( $mock ),
-                       function () use ( $mock ) {
+               $api->getModuleManager()->addModule( 'testmodule', 'action', [
+                       'class' => get_class( $mock ),
+                       'factory' => function () use ( $mock ) {
                                return $mock;
                        }
-               );
+               );
                $api->execute();
        }
 
@@ -260,11 +261,12 @@ class ApiMainTest extends ApiTestCase {
                $mock->method( 'mustBePosted' )->willReturn( false );
 
                $api = new ApiMain( new FauxRequest( [ 'action' => 'testmodule' ] ) );
-               $api->getModuleManager()->addModule( 'testmodule', 'action', get_class( $mock ),
-                       function () use ( $mock ) {
+               $api->getModuleManager()->addModule( 'testmodule', 'action', [
+                       'class' => get_class( $mock ),
+                       'factory' => function () use ( $mock ) {
                                return $mock;
                        }
-               );
+               );
                $api->execute();
        }
 
@@ -309,11 +311,12 @@ class ApiMainTest extends ApiTestCase {
                $req->setRequestURL( "http://localhost" );
 
                $api = new ApiMain( $req );
-               $api->getModuleManager()->addModule( 'testmodule', 'action', get_class( $mock ),
-                       function () use ( $mock ) {
+               $api->getModuleManager()->addModule( 'testmodule', 'action', [
+                       'class' => get_class( $mock ),
+                       'factory' => function () use ( $mock ) {
                                return $mock;
                        }
-               );
+               );
 
                $wrapper = TestingAccessWrapper::newFromObject( $api );
                $wrapper->mInternalMode = false;
index b01b90e..e99e9a9 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
+use Wikimedia\ObjectFactory;
+
 /**
  * @covers ApiModuleManager
  *
@@ -12,7 +15,8 @@ class ApiModuleManagerTest extends MediaWikiTestCase {
        private function getModuleManager() {
                $request = new FauxRequest();
                $main = new ApiMain( $request );
-               return new ApiModuleManager( $main );
+
+               return new ApiModuleManager( $main, MediaWikiServices::getInstance()->getObjectFactory() );
        }
 
        public function newApiLogin( $main, $action ) {
@@ -28,30 +32,61 @@ class ApiModuleManagerTest extends MediaWikiTestCase {
                                null,
                        ],
 
-                       'with factory' => [
+                       'with class and factory' => [
                                'login',
                                'action',
                                ApiLogin::class,
                                [ $this, 'newApiLogin' ],
                        ],
 
-                       'with closure' => [
-                               'logout',
+                       'with spec (class only)' => [
+                               'login',
                                'action',
-                               ApiLogout::class,
-                               function ( ApiMain $main, $action ) {
-                                       return new ApiLogout( $main, $action );
-                               },
+                               [
+                                       'class' => ApiLogin::class
+                               ],
+                               null,
+                       ],
+
+                       'with spec' => [
+                               'login',
+                               'action',
+                               [
+                                       'class' => ApiLogin::class,
+                                       'factory' => [ $this, 'newApiLogin' ],
+                               ],
+                               null,
                        ],
+
+                       'with spec (using services)' => [
+                               'logout',
+                               'action',
+                               [
+                                       'class' => ApiLogout::class,
+                                       'factory' => function ( ApiMain $main, $action, ObjectFactory $objectFactory ) {
+                                               return new ApiLogout( $main, $action );
+                                       },
+                                       'services' => [
+                                               'ObjectFactory'
+                                       ],
+                               ],
+                               null,
+                       ]
                ];
        }
 
        /**
         * @dataProvider addModuleProvider
         */
-       public function testAddModule( $name, $group, $class, $factory = null ) {
+       public function testAddModule( $name, $group, $spec, $factory ) {
+               if ( $factory ) {
+                       $this->hideDeprecated(
+                               ApiModuleManager::class . '::addModule with $class and $factory'
+                       );
+               }
+
                $moduleManager = $this->getModuleManager();
-               $moduleManager->addModule( $name, $group, $class, $factory );
+               $moduleManager->addModule( $name, $group, $spec, $factory );
 
                $this->assertTrue( $moduleManager->isDefined( $name, $group ), 'isDefined' );
                $this->assertNotNull( $moduleManager->getModule( $name, $group, true ), 'getModule' );
@@ -327,4 +362,22 @@ class ApiModuleManagerTest extends MediaWikiTestCase {
                        $moduleManager->getClassName( 'nonexistentmodule' )
                );
        }
+
+       /**
+        * @expectedException \InvalidArgumentException
+        * @expectedExceptionMessage $spec must define a class name
+        */
+       public function testAddModuleWithIncompleteSpec() {
+               $moduleManager = $this->getModuleManager();
+
+               $moduleManager->addModule(
+                       'logout',
+                       'action',
+                       [
+                               'factory' => function ( ApiMain $main, $action ) {
+                                       return new ApiLogout( $main, $action );
+                               },
+                       ]
+               );
+       }
 }
index b9e4645..fdc9c1b 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
+use Wikimedia\TestingAccessWrapper;
+
 /**
  * @group API
  * @group medium
@@ -176,4 +179,44 @@ class ApiPageSetTest extends ApiTestCase {
                        3 => [ "$userDbkey/subpage" => -3 ],
                ], $pageSet->getAllTitlesByNamespace() );
        }
+
+       /**
+        * Test that ApiPageSet is calling GenderCache for provided user names to prefill the
+        * GenderCache and avoid a performance issue when loading each users' gender on it's own.
+        * The test is setting the "missLimit" to 0 on the GenderCache to trigger misses logic.
+        * When the "misses" property is no longer 0 at the end of the test,
+        * something was requested which is not part of the cache. Than the test is failing.
+        */
+       public function testGenderCaching() {
+               // Set up the user namespace to have gender aliases to trigger the gender cache
+               $this->setMwGlobals( [
+                       'wgExtraGenderNamespaces' => [ NS_USER => [ 'male' => 'Male', 'female' => 'Female' ] ]
+               ] );
+               $this->overrideMwServices();
+
+               // User names to test with - it is not needed that the user exists in the database
+               // to trigger gender cache
+               $userNames = [
+                       'Female',
+                       'Unknown',
+                       'Male',
+               ];
+
+               // Prepare the gender cache for testing - this is a fresh instance due to service override
+               $genderCache = TestingAccessWrapper::newFromObject(
+                       MediaWikiServices::getInstance()->getGenderCache()
+               );
+               $genderCache->missLimit = 0;
+
+               // Do an api request to trigger ApiPageSet code
+               $this->doApiRequest( [
+                       'action' => 'query',
+                       'titles' => 'User:' . implode( '|User:', $userNames ),
+               ] );
+
+               $this->assertEquals( 0, $genderCache->misses,
+                       'ApiPageSet does not prefill the gender cache correctly' );
+               $this->assertEquals( $userNames, array_keys( $genderCache->cache ),
+                       'ApiPageSet does not prefill all users into the gender cache' );
+       }
 }
index 6bbdd3b..771e039 100644 (file)
@@ -44,14 +44,16 @@ class ApiQueryLanguageinfoTest extends ApiTestCase {
                                        $moduleManager->addModule(
                                                'languageinfo',
                                                'meta',
-                                               ApiQueryLanguageinfo::class,
-                                               function ( $parent, $name ) use ( $microtimeFunction ) {
-                                                       return new ApiQueryLanguageinfo(
-                                                               $parent,
-                                                               $name,
-                                                               $microtimeFunction
-                                                       );
-                                               }
+                                               [
+                                                       'class' => ApiQueryLanguageinfo::class,
+                                                       'factory' => function ( $parent, $name ) use ( $microtimeFunction ) {
+                                                               return new ApiQueryLanguageinfo(
+                                                                       $parent,
+                                                                       $name,
+                                                                       $microtimeFunction
+                                                               );
+                                                       }
+                                               ]
                                        );
                                }
                        );
index a4ca8a1..7dc63fb 100644 (file)
@@ -1,5 +1,8 @@
 <?php
 
+use MediaWiki\Block\DatabaseBlock;
+use MediaWiki\Block\Restriction\PageRestriction;
+
 /**
  * Tests for action=revisiondelete
  * @covers APIRevisionDelete
@@ -22,8 +25,7 @@ class ApiRevisionDeleteTest extends ApiTestCase {
                // Make a few edits for us to play with
                for ( $i = 1; $i <= 5; $i++ ) {
                        self::editPage( self::$page, MWCryptRand::generateHex( 10 ), 'summary' );
-                       $this->revs[] = Title::newFromText( self::$page )
-                               ->getLatestRevID( Title::GAID_FOR_UPDATE );
+                       $this->revs[] = Title::newFromText( self::$page )->getLatestRevID( Title::READ_LATEST );
                }
        }
 
@@ -114,4 +116,32 @@ class ApiRevisionDeleteTest extends ApiTestCase {
                $this->assertTrue( $item['texthidden'], 'texthidden' );
                $this->assertEquals( $item['id'], $revid );
        }
+
+       public function testPartiallyBlockedPage() {
+               $this->setExpectedApiException( 'apierror-blocked-partial' );
+
+               $user = static::getTestSysop()->getUser();
+
+               $block = new DatabaseBlock( [
+                       'address' => $user,
+                       'by' => static::getTestSysop()->getUser()->getId(),
+                       'sitewide' => false,
+               ] );
+
+               $block->setRestrictions( [
+                       new PageRestriction( 0, Title::newFromText( self::$page )->getArticleID() )
+               ] );
+               $block->insert();
+
+               $revid = array_shift( $this->revs );
+
+               $this->doApiRequest( [
+                       'action' => 'revisiondelete',
+                       'type' => 'revision',
+                       'target' => self::$page,
+                       'ids' => $revid,
+                       'hide' => 'content|user|comment',
+                       'token' => $user->getEditToken(),
+               ] );
+       }
 }
index 03359f8..286e8a8 100644 (file)
@@ -365,13 +365,19 @@ class ApiFormatBaseTest extends ApiFormatTestBase {
                $main = new ApiMain( $context );
                $printer = $this->getMockFormatter( $main, 'mockfm' );
                $mm = $printer->getMain()->getModuleManager();
-               $mm->addModule( 'mockfm', 'format', ApiFormatBase::class, function () {
-                       return $mock;
-               } );
-               if ( $registerNonHtml ) {
-                       $mm->addModule( 'mock', 'format', ApiFormatBase::class, function () {
+               $mm->addModule( 'mockfm', 'format', [
+                       'class' => ApiFormatBase::class,
+                       'factory' => function () {
                                return $mock;
-                       } );
+                       }
+               ] );
+               if ( $registerNonHtml ) {
+                       $mm->addModule( 'mock', 'format', [
+                               'class' => ApiFormatBase::class,
+                               'factory' => function () {
+                                       return $mock;
+                               }
+                       ] );
                }
 
                $printer->initPrinter();
index 27ec73a..789908c 100644 (file)
@@ -27,7 +27,6 @@ abstract class ApiFormatTestBase extends MediaWikiTestCase {
         *  - class: If set, register 'name' with this class (and 'factory', if that's set)
         *  - factory: Used with 'class' to register at runtime
         *  - returnPrinter: Return the printer object
-        * @param callable|null $factory Factory to use instead of the normal one
         * @return string|array The string if $options['returnPrinter'] isn't set, or an array if it is:
         *  - text: Output text string
         *  - printer: ApiFormatBase
@@ -44,8 +43,15 @@ abstract class ApiFormatTestBase extends MediaWikiTestCase {
                $context->setRequest( new FauxRequest( $params, true ) );
                $main = new ApiMain( $context );
                if ( isset( $options['class'] ) ) {
-                       $factory = $options['factory'] ?? null;
-                       $main->getModuleManager()->addModule( $printerName, 'format', $options['class'], $factory );
+                       $spec = [
+                               'class' => $options['class']
+                       ];
+
+                       if ( isset( $options['factory'] ) ) {
+                               $spec['factory'] = $options['factory'];
+                       }
+
+                       $main->getModuleManager()->addModule( $printerName, 'format', $spec );
                }
                $result = $main->getResult();
                $result->addArrayType( null, 'default' );
index 301ed10..df643d2 100644 (file)
@@ -8,15 +8,6 @@
  */
 class ApiQueryUserContribsTest extends ApiTestCase {
        public function addDBDataOnce() {
-               global $wgActorTableSchemaMigrationStage;
-
-               $reset = new \Wikimedia\ScopedCallback( function ( $v ) {
-                       $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', $v );
-               }, [ $wgActorTableSchemaMigrationStage ] );
-               // Needs to WRITE_BOTH so READ_OLD tests below work. READ mode here doesn't really matter.
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage',
-                       SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW );
-
                $users = [
                        User::newFromName( '192.168.2.2', false ),
                        User::newFromName( '192.168.2.1', false ),
@@ -43,17 +34,14 @@ class ApiQueryUserContribsTest extends ApiTestCase {
 
        /**
         * @dataProvider provideSorting
-        * @param int $stage SCHEMA_COMPAT contants for $wgActorTableSchemaMigrationStage
         * @param array $params Extra parameters for the query
         * @param bool $reverse Reverse order?
         * @param int $revs Number of revisions to expect
         */
-       public function testSorting( $stage, $params, $reverse, $revs ) {
+       public function testSorting( $params, $reverse, $revs ) {
                // FIXME: fails under sqlite
                $this->markTestSkippedIfDbType( 'sqlite' );
 
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', $stage );
-
                if ( isset( $params['ucuserids'] ) ) {
                        $params['ucuserids'] = implode( '|', array_map( 'User::idFromName', $params['ucuserids'] ) );
                }
@@ -116,38 +104,23 @@ class ApiQueryUserContribsTest extends ApiTestCase {
                $users2 = [ __CLASS__ . ' A', __CLASS__ . ' B', __CLASS__ . ' D' ];
                $ips = [ '192.168.2.1', '192.168.2.2', '192.168.2.3', '192.168.2.4' ];
 
-               foreach (
-                       [
-                               'old' => SCHEMA_COMPAT_OLD,
-                               'read old' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
-                               'read new' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
-                               'new' => SCHEMA_COMPAT_NEW,
-                       ] as $stageName => $stage
-               ) {
-                       foreach ( [ false, true ] as $reverse ) {
-                               $name = $stageName . ( $reverse ? ', reverse' : '' );
-                               yield "Named users, $name" => [ $stage, [ 'ucuser' => $users ], $reverse, 9 ];
-                               yield "Named users including a no-edit user, $name" => [
-                                       $stage, [ 'ucuser' => $users2 ], $reverse, 6
-                               ];
-                               yield "IP users, $name" => [ $stage, [ 'ucuser' => $ips ], $reverse, 9 ];
-                               yield "All users, $name" => [
-                                       $stage, [ 'ucuser' => array_merge( $users, $ips ) ], $reverse, 18
-                               ];
-                               yield "User IDs, $name" => [ $stage, [ 'ucuserids' => $users ], $reverse, 9 ];
-                               yield "Users by prefix, $name" => [ $stage, [ 'ucuserprefix' => __CLASS__ ], $reverse, 9 ];
-                               yield "IPs by prefix, $name" => [ $stage, [ 'ucuserprefix' => '192.168.2.' ], $reverse, 9 ];
-                       }
+               foreach ( [ false, true ] as $reverse ) {
+                       $name = ( $reverse ? ', reverse' : '' );
+                       yield "Named users, $name" => [ [ 'ucuser' => $users ], $reverse, 9 ];
+                       yield "Named users including a no-edit user, $name" => [
+                               [ 'ucuser' => $users2 ], $reverse, 6
+                       ];
+                       yield "IP users, $name" => [ [ 'ucuser' => $ips ], $reverse, 9 ];
+                       yield "All users, $name" => [
+                               [ 'ucuser' => array_merge( $users, $ips ) ], $reverse, 18
+                       ];
+                       yield "User IDs, $name" => [ [ 'ucuserids' => $users ], $reverse, 9 ];
+                       yield "Users by prefix, $name" => [ [ 'ucuserprefix' => __CLASS__ ], $reverse, 9 ];
+                       yield "IPs by prefix, $name" => [ [ 'ucuserprefix' => '192.168.2.' ], $reverse, 9 ];
                }
        }
 
-       /**
-        * @dataProvider provideInterwikiUser
-        * @param int $stage SCHEMA_COMPAT constants for $wgActorTableSchemaMigrationStage
-        */
-       public function testInterwikiUser( $stage ) {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', $stage );
-
+       public function testInterwikiUser() {
                $params = [
                        'action' => 'query',
                        'list' => 'usercontribs',
@@ -174,13 +147,4 @@ class ApiQueryUserContribsTest extends ApiTestCase {
                $this->assertSame( $sorted, $ids, "IDs are sorted" );
        }
 
-       public static function provideInterwikiUser() {
-               return [
-                       'old' => [ SCHEMA_COMPAT_OLD ],
-                       'read old' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD ],
-                       'read new' => [ SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW ],
-                       'new' => [ SCHEMA_COMPAT_NEW ],
-               ];
-       }
-
 }
index d4133b7..6a00e67 100644 (file)
@@ -54,8 +54,6 @@ class BlockManagerTest extends MediaWikiTestCase {
                                BlockManager::$constructorOptions,
                                MediaWikiServices::getInstance()->getMainConfig()
                        ),
-                       $this->user,
-                       $this->user->getRequest(),
                        MediaWikiServices::getInstance()->getPermissionManager()
                ];
        }
index cd3ddfa..1f9d29e 100644 (file)
@@ -430,4 +430,18 @@ class LinksUpdateTest extends MediaWikiLangTestCase {
                        $queueGroup->ack( $job );
                }
        }
+
+       public function testIsRecursive() {
+               list( $title, $po ) = $this->makeTitleAndParserOutput( 'Test', 1 );
+               $linksUpdate = new LinksUpdate( $title, $po );
+               $this->assertTrue( $linksUpdate->isRecursive(), 'LinksUpdate is recursive by default' );
+
+               $linksUpdate = new LinksUpdate( $title, $po, true );
+               $this->assertTrue( $linksUpdate->isRecursive(),
+                       'LinksUpdate is recursive when asked to be recursive' );
+
+               $linksUpdate = new LinksUpdate( $title, $po, false );
+               $this->assertFalse( $linksUpdate->isRecursive(),
+                       'LinksUpdate is not recursive when asked to be not recursive' );
+       }
 }
index b183cde..a7040e0 100644 (file)
@@ -29,18 +29,12 @@ class DatabaseLogEntryTest extends MediaWikiTestCase {
         * @param array $selectFields
         * @param string[]|null $row
         * @param string[]|null $expectedFields
-        * @param int $actorMigration
         */
        public function testNewFromId( $id,
                array $selectFields,
                array $row = null,
-               array $expectedFields = null,
-               $actorMigration
+               array $expectedFields = null
        ) {
-               $this->setMwGlobals( [
-                       'wgActorTableSchemaMigrationStage' => $actorMigration,
-               ] );
-
                $row = $row ? (object)$row : null;
                $db = $this->getMock( IDatabase::class );
                $db->expects( self::once() )
@@ -67,36 +61,6 @@ class DatabaseLogEntryTest extends MediaWikiTestCase {
        }
 
        public function provideNewFromId() {
-               $oldTables = [
-                       'tables' => [
-                               'logging', 'user',
-                               'comment_log_comment' => 'comment',
-                       ],
-                       'fields' => [
-                               'log_id',
-                               'log_type',
-                               'log_action',
-                               'log_timestamp',
-                               'log_namespace',
-                               'log_title',
-                               'log_params',
-                               'log_deleted',
-                               'user_id',
-                               'user_name',
-                               'user_editcount',
-                               'log_comment_text' => 'comment_log_comment.comment_text',
-                               'log_comment_data' => 'comment_log_comment.comment_data',
-                               'log_comment_cid' => 'comment_log_comment.comment_id',
-                               'log_user' => 'log_user',
-                               'log_user_text' => 'log_user_text',
-                               'log_actor' => 'NULL',
-                       ],
-                       'options' => [],
-                       'join_conds' => [
-                               'user' => [ 'LEFT JOIN', 'user_id=log_user' ],
-                               'comment_log_comment' => [ 'JOIN', 'comment_log_comment.comment_id = log_comment_id' ],
-                       ],
-               ];
                $newTables = [
                        'tables' => [
                                'logging',
@@ -133,22 +97,20 @@ class DatabaseLogEntryTest extends MediaWikiTestCase {
                return [
                        [
                                0,
-                               $oldTables + [ 'conds' => [ 'log_id' => 0 ] ],
-                               null,
+                               $newTables + [ 'conds' => [ 'log_id' => 0 ] ],
                                null,
-                               SCHEMA_COMPAT_OLD,
+                               null
                        ],
                        [
                                123,
-                               $oldTables + [ 'conds' => [ 'log_id' => 123 ] ],
+                               $newTables + [ 'conds' => [ 'log_id' => 123 ] ],
                                [
                                        'log_id' => 123,
                                        'log_type' => 'foobarize',
                                        'log_comment_text' => 'test!',
                                        'log_comment_data' => null,
                                ],
-                               [ 'type' => 'foobarize', 'comment' => 'test!' ],
-                               SCHEMA_COMPAT_OLD,
+                               [ 'type' => 'foobarize', 'comment' => 'test!' ]
                        ],
                        [
                                567,
@@ -159,8 +121,7 @@ class DatabaseLogEntryTest extends MediaWikiTestCase {
                                        'log_comment_text' => 'test!',
                                        'log_comment_data' => null,
                                ],
-                               [ 'type' => 'foobarize', 'comment' => 'test!' ],
-                               SCHEMA_COMPAT_NEW,
+                               [ 'type' => 'foobarize', 'comment' => 'test!' ]
                        ],
                ];
        }
index 6c56510..4a0a6d0 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /**
  * @todo Could use a test of extended XMP segments. Hard to find programs that
- * create example files, and creating my own in vim propbably wouldn't
+ * create example files, and creating my own in vim probably wouldn't
  * serve as a very good "test". (Adobe photoshop probably creates such files
  * but it costs money). The implementation of it currently in MediaWiki is based
  * solely on reading the standard, without any real world test files.
@@ -76,6 +76,12 @@ class JpegMetadataExtractorTest extends MediaWikiIntegrationTestCase {
                $this->assertEquals( $expected, bin2hex( $res['PSIR'][0] ) );
        }
 
+       public function testXMPExtractionNullChar() {
+               $res = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-xmp-nullchar.jpg' );
+               $expected = file_get_contents( $this->filePath . 'jpeg-xmp-psir.xmp' );
+               $this->assertEquals( $expected, $res['XMP'] );
+       }
+
        public function testXMPExtractionAltAppId() {
                $res = JpegMetadataExtractor::segmentSplitter( $this->filePath . 'jpeg-xmp-alt.jpg' );
                $expected = file_get_contents( $this->filePath . 'jpeg-xmp-psir.xmp' );
index bcbc1ed..90b118c 100644 (file)
@@ -84,7 +84,6 @@ abstract class PageArchiveTestBase extends MediaWikiTestCase {
                $this->tablesUsed += $this->getMcrTablesToReset();
 
                $this->setMwGlobals( [
-                       'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
                        'wgContentHandlerUseDB' => $this->getContentHandlerUseDB(),
                        'wgMultiContentRevisionSchemaMigrationStage' => $this->getMcrMigrationStage(),
                ] );
index e7f7067..a459441 100644 (file)
@@ -2,6 +2,7 @@
 
 use MediaWiki\Auth\AuthManager;
 use MediaWiki\MediaWikiServices;
+use MediaWiki\Permissions\PermissionManager;
 use MediaWiki\Preferences\DefaultPreferencesFactory;
 use Wikimedia\TestingAccessWrapper;
 
@@ -49,9 +50,10 @@ class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
 
        /**
         * Get a basic PreferencesFactory for testing with.
+        * @param PermissionManager|null $manager
         * @return DefaultPreferencesFactory
         */
-       protected function getPreferencesFactory() {
+       protected function getPreferencesFactory( PermissionManager $manager = null ) {
                $mockNsInfo = $this->createMock( NamespaceInfo::class );
                $mockNsInfo->method( 'getValidNamespaces' )->willReturn( [
                        NS_MAIN, NS_TALK, NS_USER, NS_USER_TALK
@@ -59,13 +61,16 @@ class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
                $mockNsInfo->expects( $this->never() )
                        ->method( $this->anythingBut( 'getValidNamespaces', '__destruct' ) );
 
+               $mockPermissionManager = $manager ?? $this->createMock( PermissionManager::class );
+
                return new DefaultPreferencesFactory(
                        new LoggedServiceOptions( self::$serviceOptionsAccessLog,
                                DefaultPreferencesFactory::$constructorOptions, $this->config ),
                        new Language(),
                        AuthManager::singleton(),
                        MediaWikiServices::getInstance()->getLinkRenderer(),
-                       $mockNsInfo
+                       $mockNsInfo,
+                       $mockPermissionManager
                );
        }
 
@@ -88,7 +93,9 @@ class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
         * @dataProvider emailAuthenticationProvider
         */
        public function testEmailAuthentication( $user, $cssClass ) {
-               $prefs = $this->getPreferencesFactory()->getFormDescriptor( $user, $this->context );
+               $pm = $this->createMock( PermissionManager::class );
+               $pm->method( 'userHasRight' )->willReturn( true );
+               $prefs = $this->getPreferencesFactory( $pm )->getFormDescriptor( $user, $this->context );
                $this->assertArrayHasKey( 'cssclass', $prefs['emailauthentication'] );
                $this->assertEquals( $cssClass, $prefs['emailauthentication']['cssclass'] );
        }
@@ -100,16 +107,18 @@ class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
                $userMock = $this->getMockBuilder( User::class )
                        ->disableOriginalConstructor()
                        ->getMock();
-               $userMock->method( 'isAllowed' )
-                       ->willReturn( false );
                $userMock->method( 'getEffectiveGroups' )
                        ->willReturn( [] );
                $userMock->method( 'getGroupMemberships' )
                        ->willReturn( [] );
                $userMock->method( 'getOptions' )
                        ->willReturn( [ 'test' => 'yes' ] );
-
-               $prefs = $this->getPreferencesFactory()->getFormDescriptor( $userMock, $this->context );
+               $pm = $this->createMock( PermissionManager::class );
+               $pm->method( 'userHasRight' )
+                       ->will( $this->returnValueMap( [
+                               [ $userMock, 'editmyoptions', true ]
+                       ] ) );
+               $prefs = $this->getPreferencesFactory( $pm )->getFormDescriptor( $userMock, $this->context );
                $this->assertArrayNotHasKey( 'showrollbackconfirmation', $prefs );
        }
 
@@ -120,16 +129,19 @@ class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
                $userMock = $this->getMockBuilder( User::class )
                        ->disableOriginalConstructor()
                        ->getMock();
-               $userMock->method( 'isAllowed' )
-                       ->willReturn( true );
                $userMock->method( 'getEffectiveGroups' )
                        ->willReturn( [] );
                $userMock->method( 'getGroupMemberships' )
                        ->willReturn( [] );
                $userMock->method( 'getOptions' )
                        ->willReturn( [ 'test' => 'yes' ] );
-
-               $prefs = $this->getPreferencesFactory()->getFormDescriptor( $userMock, $this->context );
+               $pm = $this->createMock( PermissionManager::class );
+               $pm->method( 'userHasRight' )
+                       ->will( $this->returnValueMap( [
+                               [ $userMock, 'editmyoptions', true ],
+                               [ $userMock, 'rollback', true ]
+                       ] ) );
+               $prefs = $this->getPreferencesFactory( $pm )->getFormDescriptor( $userMock, $this->context );
                $this->assertArrayHasKey( 'showrollbackconfirmation', $prefs );
                $this->assertEquals(
                        'rendering/advancedrendering',
@@ -181,10 +193,6 @@ class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
                        ->getMock();
                $userMock->method( 'getOptions' )
                        ->willReturn( $oldOptions );
-               $userMock->method( 'isAllowedAny' )
-                       ->willReturn( true );
-               $userMock->method( 'isAllowed' )
-                       ->willReturn( true );
 
                $userMock->expects( $this->exactly( 2 ) )
                        ->method( 'setOption' )
@@ -193,18 +201,25 @@ class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
                                [ $this->equalTo( 'option' ), $this->equalTo( $newOptions[ 'option' ] ) ]
                        );
 
-               $form->expects( $this->any() )
-                       ->method( 'getModifiedUser' )
+               $form->method( 'getModifiedUser' )
                        ->willReturn( $userMock );
 
-               $form->expects( $this->any() )
-                       ->method( 'getContext' )
+               $form->method( 'getContext' )
                        ->willReturn( $this->context );
 
-               $form->expects( $this->any() )
-                       ->method( 'getConfig' )
+               $form->method( 'getConfig' )
                        ->willReturn( $configMock );
 
+               $pm = $this->createMock( PermissionManager::class );
+               $pm->method( 'userHasAnyRight' )
+                       ->will( $this->returnValueMap( [
+                               [ $userMock, 'editmyprivateinfo', 'editmyoptions', true ]
+                       ] ) );
+               $pm->method( 'userHasRight' )
+                       ->will( $this->returnValueMap( [
+                               [ $userMock, 'editmyoptions', true ]
+                       ] ) );
+
                $this->setTemporaryHook( 'PreferencesFormPreSave',
                        function ( $formData, $form, $user, &$result, $oldUserOptions )
                                use ( $newOptions, $oldOptions, $userMock ) {
@@ -220,7 +235,7 @@ class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
                );
 
                /** @var DefaultPreferencesFactory $factory */
-               $factory = TestingAccessWrapper::newFromObject( $this->getPreferencesFactory() );
+               $factory = TestingAccessWrapper::newFromObject( $this->getPreferencesFactory( $pm ) );
                $factory->saveFormData( $newOptions, $form, [] );
        }
 
@@ -233,7 +248,14 @@ class DefaultPreferencesFactoryTest extends \MediaWikiTestCase {
                // Test a string with leading zeros (i.e. not octal) and spaces.
                $this->context->getRequest()->setVal( 'wprclimit', ' 0012 ' );
                $user = new User;
-               $form = $this->getPreferencesFactory()->getForm( $user, $this->context );
+               $pm = $this->createMock( PermissionManager::class );
+               $pm->method( 'userHasAnyRight' )
+                       ->willReturn( true );
+               $pm->method( 'userHasRight' )
+                       ->will( $this->returnValueMap( [
+                               [ $user, 'editmyoptions', true ]
+                       ] ) );
+               $form = $this->getPreferencesFactory( $pm )->getForm( $user, $this->context );
                $form->show();
                $form->trySubmit();
                $this->assertEquals( 12, $user->getOption( 'rclimit' ) );
index cd0867d..b2f525d 100644 (file)
@@ -259,14 +259,14 @@ class SessionManagerTest extends MediaWikiTestCase {
                try {
                        $manager->getSessionForRequest( $request );
                        $this->fail( 'Expcected exception not thrown' );
-               } catch ( \OverflowException $ex ) {
+               } catch ( SessionOverflowException $ex ) {
                        $this->assertStringStartsWith(
                                'Multiple sessions for this request tied for top priority: ',
                                $ex->getMessage()
                        );
-                       $this->assertCount( 2, $ex->sessionInfos );
-                       $this->assertContains( $request->info1, $ex->sessionInfos );
-                       $this->assertContains( $request->info2, $ex->sessionInfos );
+                       $this->assertCount( 2, $ex->getSessionInfos() );
+                       $this->assertContains( $request->info1, $ex->getSessionInfos() );
+                       $this->assertContains( $request->info2, $ex->getSessionInfos() );
                }
                $this->assertFalse( $request->unpersist1 );
                $this->assertFalse( $request->unpersist2 );
index 68433c6..ff3e714 100644 (file)
@@ -224,8 +224,6 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
        }
 
        public function testRcHidemyselfFilter() {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
-
                $user = $this->getTestUser()->getUser();
                $user->getActorId( wfGetDB( DB_MASTER ) );
                $this->assertConditions(
@@ -253,41 +251,7 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
                );
        }
 
-       public function testRcHidemyselfFilter_old() {
-               $this->setMwGlobals(
-                       'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
-               );
-
-               $user = $this->getTestUser()->getUser();
-               $user->getActorId( wfGetDB( DB_MASTER ) );
-               $this->assertConditions(
-                       [ # expected
-                               "NOT((rc_user = '{$user->getId()}'))",
-                       ],
-                       [
-                               'hidemyself' => 1,
-                       ],
-                       "rc conditions: hidemyself=1 (logged in)",
-                       $user
-               );
-
-               $user = User::newFromName( '10.11.12.13', false );
-               $id = $user->getActorId( wfGetDB( DB_MASTER ) );
-               $this->assertConditions(
-                       [ # expected
-                               "NOT((rc_user_text = '10.11.12.13'))",
-                       ],
-                       [
-                               'hidemyself' => 1,
-                       ],
-                       "rc conditions: hidemyself=1 (anon)",
-                       $user
-               );
-       }
-
        public function testRcHidebyothersFilter() {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
-
                $user = $this->getTestUser()->getUser();
                $user->getActorId( wfGetDB( DB_MASTER ) );
                $this->assertConditions(
@@ -315,38 +279,6 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
                );
        }
 
-       public function testRcHidebyothersFilter_old() {
-               $this->setMwGlobals(
-                       'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
-               );
-
-               $user = $this->getTestUser()->getUser();
-               $user->getActorId( wfGetDB( DB_MASTER ) );
-               $this->assertConditions(
-                       [ # expected
-                               "(rc_user_text = '{$user->getName()}')",
-                       ],
-                       [
-                               'hidebyothers' => 1,
-                       ],
-                       "rc conditions: hidebyothers=1 (logged in)",
-                       $user
-               );
-
-               $user = User::newFromName( '10.11.12.13', false );
-               $id = $user->getActorId( wfGetDB( DB_MASTER ) );
-               $this->assertConditions(
-                       [ # expected
-                               "(rc_user_text = '10.11.12.13')",
-                       ],
-                       [
-                               'hidebyothers' => 1,
-                       ],
-                       "rc conditions: hidebyothers=1 (anon)",
-                       $user
-               );
-       }
-
        public function testRcHidepageedits() {
                $this->assertConditions(
                        [ # expected
@@ -550,8 +482,6 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
        }
 
        public function testFilterUserExpLevelAllExperienceLevels() {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
-
                $this->assertConditions(
                        [
                                # expected
@@ -564,26 +494,7 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
                );
        }
 
-       public function testFilterUserExpLevelAllExperienceLevels_old() {
-               $this->setMwGlobals(
-                       'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
-               );
-
-               $this->assertConditions(
-                       [
-                               # expected
-                               'rc_user != 0',
-                       ],
-                       [
-                               'userExpLevel' => 'newcomer;learner;experienced',
-                       ],
-                       "rc conditions: userExpLevel=newcomer;learner;experienced"
-               );
-       }
-
-       public function testFilterUserExpLevelRegistrered() {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
-
+       public function testFilterUserExpLevelRegistered() {
                $this->assertConditions(
                        [
                                # expected
@@ -596,26 +507,7 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
                );
        }
 
-       public function testFilterUserExpLevelRegistrered_old() {
-               $this->setMwGlobals(
-                       'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
-               );
-
-               $this->assertConditions(
-                       [
-                               # expected
-                               'rc_user != 0',
-                       ],
-                       [
-                               'userExpLevel' => 'registered',
-                       ],
-                       "rc conditions: userExpLevel=registered"
-               );
-       }
-
-       public function testFilterUserExpLevelUnregistrered() {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
-
+       public function testFilterUserExpLevelUnregistered() {
                $this->assertConditions(
                        [
                                # expected
@@ -628,26 +520,7 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
                );
        }
 
-       public function testFilterUserExpLevelUnregistrered_old() {
-               $this->setMwGlobals(
-                       'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
-               );
-
-               $this->assertConditions(
-                       [
-                               # expected
-                               'rc_user = 0',
-                       ],
-                       [
-                               'userExpLevel' => 'unregistered',
-                       ],
-                       "rc conditions: userExpLevel=unregistered"
-               );
-       }
-
-       public function testFilterUserExpLevelRegistreredOrLearner() {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
-
+       public function testFilterUserExpLevelRegisteredOrLearner() {
                $this->assertConditions(
                        [
                                # expected
@@ -660,26 +533,7 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
                );
        }
 
-       public function testFilterUserExpLevelRegistreredOrLearner_old() {
-               $this->setMwGlobals(
-                       'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
-               );
-
-               $this->assertConditions(
-                       [
-                               # expected
-                               'rc_user != 0',
-                       ],
-                       [
-                               'userExpLevel' => 'registered;learner',
-                       ],
-                       "rc conditions: userExpLevel=registered;learner"
-               );
-       }
-
-       public function testFilterUserExpLevelUnregistreredOrExperienced() {
-               $this->setMwGlobals( 'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_NEW );
-
+       public function testFilterUserExpLevelUnregisteredOrExperienced() {
                $conds = $this->buildQuery( [ 'userExpLevel' => 'unregistered;experienced' ] );
 
                $this->assertRegExp(
@@ -690,21 +544,6 @@ class ChangesListSpecialPageTest extends AbstractChangesListSpecialPageTestCase
                );
        }
 
-       public function testFilterUserExpLevelUnregistreredOrExperienced_old() {
-               $this->setMwGlobals(
-                       'wgActorTableSchemaMigrationStage', SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD
-               );
-
-               $conds = $this->buildQuery( [ 'userExpLevel' => 'unregistered;experienced' ] );
-
-               $this->assertRegExp(
-                       '/\(rc_user = 0\) OR '
-                               . '\(\(user_editcount >= 500\) AND \(user_registration <= \'[^\']+\'\)\)/',
-                       reset( $conds ),
-                       "rc conditions: userExpLevel=unregistered;experienced"
-               );
-       }
-
        public function testFilterUserExpLevel() {
                $now = time();
                $this->setMwGlobals( [
index c0376ad..a5d5946 100644 (file)
@@ -60,6 +60,10 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
                        'callback array' => [
                                [ 'SpecialPageTestHelper', 'newSpecialAllPages' ],
                                false
+                       ],
+                       'object factory spec' => [
+                               [ 'class' => SpecialAllPages::class ],
+                               false
                        ]
                ];
        }
@@ -264,4 +268,29 @@ class SpecialPageFactoryTest extends MediaWikiTestCase {
                $this->assertTrue( $called, 'Recursive call succeeded' );
        }
 
+       /**
+        * @covers \MediaWiki\Special\SpecialPageFactory::getPage
+        */
+       public function testSpecialPageCreationThatRequiresService() {
+               $type = null;
+
+               $this->setMwGlobals( 'wgSpecialPages',
+                       [ 'TestPage' => [
+                               'factory' => function ( $spf ) use ( &$type ) {
+                                       $type = get_class( $spf );
+
+                                       return new class() extends SpecialPage {
+
+                                       };
+                               },
+                               'services' => [
+                                       'SpecialPageFactory'
+                               ]
+                       ] ]
+               );
+
+               SpecialPageFactory::getPage( 'TestPage' );
+
+               $this->assertEquals( \MediaWiki\Special\SpecialPageFactory::class, $type );
+       }
 }
index 58f83de..a95d43c 100644 (file)
@@ -22,7 +22,7 @@ class QueryAllSpecialPagesTest extends MediaWikiTestCase {
 
        /** List query pages that can not be tested automatically */
        protected $manualTest = [
-               LinkSearchPage::class
+               SpecialLinkSearch::class
        ];
 
        /**
index 879acfe..5435afa 100644 (file)
@@ -8,6 +8,11 @@
  */
 class SpecialBlankPageTest extends SpecialPageTestBase {
 
+       protected function setUp() {
+               parent::setUp();
+               $this->setUserLang( 'qqx' );
+       }
+
        /**
         * Returns a new instance of the special page under test.
         *
@@ -19,7 +24,7 @@ class SpecialBlankPageTest extends SpecialPageTestBase {
 
        public function testHasWikiMsg() {
                list( $html, ) = $this->executeSpecialPage();
-               $this->assertContains( wfMessage( 'intentionallyblankpage' )->text(), $html );
+               $this->assertContains( '(intentionallyblankpage)', $html );
        }
 
 }
index 4ecb813..08225a6 100644 (file)
@@ -2,15 +2,15 @@
 
 /**
  * @group Database
- * @covers MIMEsearchPage
+ * @covers SpecialMIMESearch
  */
 class SpecialMIMESearchTest extends MediaWikiTestCase {
 
-       /** @var MIMEsearchPage */
+       /** @var SpecialMIMESearch */
        private $page;
 
        function setUp() {
-               $this->page = new MIMEsearchPage;
+               $this->page = new SpecialMIMESearch;
                $context = new RequestContext();
                $context->setTitle( Title::makeTitle( NS_SPECIAL, 'MIMESearch' ) );
                $context->setRequest( new FauxRequest() );
diff --git a/tests/phpunit/includes/specials/SpecialShortPagesTest.php b/tests/phpunit/includes/specials/SpecialShortPagesTest.php
new file mode 100644 (file)
index 0000000..8891d0d
--- /dev/null
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * Test class for SpecialShortPages class
+ *
+ * @since 1.30
+ *
+ * @license GPL-2.0-or-later
+ */
+class SpecialShortPagesTest extends MediaWikiTestCase {
+
+       /**
+        * @dataProvider provideGetQueryInfoRespectsContentNs
+        * @covers SpecialShortPages::getQueryInfo()
+        */
+       public function testGetQueryInfoRespectsContentNS( $contentNS, $blacklistNS, $expectedNS ) {
+               $this->setMwGlobals( [
+                       'wgShortPagesNamespaceBlacklist' => $blacklistNS,
+                       'wgContentNamespaces' => $contentNS
+               ] );
+               $this->setTemporaryHook( 'ShortPagesQuery', function () {
+                       // empty hook handler
+               } );
+
+               $page = new SpecialShortPages();
+               $queryInfo = $page->getQueryInfo();
+
+               $this->assertArrayHasKey( 'conds', $queryInfo );
+               $this->assertArrayHasKey( 'page_namespace', $queryInfo[ 'conds' ] );
+               $this->assertEquals( $expectedNS, $queryInfo[ 'conds' ][ 'page_namespace' ] );
+       }
+
+       public function provideGetQueryInfoRespectsContentNs() {
+               return [
+                       [ [ NS_MAIN, NS_FILE ], [], [ NS_MAIN, NS_FILE ] ],
+                       [ [ NS_MAIN, NS_TALK ], [ NS_FILE ], [ NS_MAIN, NS_TALK ] ],
+                       [ [ NS_MAIN, NS_FILE ], [ NS_FILE ], [ NS_MAIN ] ],
+                       // NS_MAIN namespace is always forced
+                       [ [], [ NS_FILE ], [ NS_MAIN ] ]
+               ];
+       }
+
+}
diff --git a/tests/phpunit/includes/specials/SpecialShortpagesTest.php b/tests/phpunit/includes/specials/SpecialShortpagesTest.php
deleted file mode 100644 (file)
index 236c5c4..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<?php
-
-/**
- * Test class for SpecialShortpages class
- *
- * @since 1.30
- *
- * @license GPL-2.0-or-later
- */
-class SpecialShortpagesTest extends MediaWikiTestCase {
-
-       /**
-        * @dataProvider provideGetQueryInfoRespectsContentNs
-        * @covers ShortPagesPage::getQueryInfo()
-        */
-       public function testGetQueryInfoRespectsContentNS( $contentNS, $blacklistNS, $expectedNS ) {
-               $this->setMwGlobals( [
-                       'wgShortPagesNamespaceBlacklist' => $blacklistNS,
-                       'wgContentNamespaces' => $contentNS
-               ] );
-               $this->setTemporaryHook( 'ShortPagesQuery', function () {
-                       // empty hook handler
-               } );
-
-               $page = new ShortPagesPage();
-               $queryInfo = $page->getQueryInfo();
-
-               $this->assertArrayHasKey( 'conds', $queryInfo );
-               $this->assertArrayHasKey( 'page_namespace', $queryInfo[ 'conds' ] );
-               $this->assertEquals( $expectedNS, $queryInfo[ 'conds' ][ 'page_namespace' ] );
-       }
-
-       public function provideGetQueryInfoRespectsContentNs() {
-               return [
-                       [ [ NS_MAIN, NS_FILE ], [], [ NS_MAIN, NS_FILE ] ],
-                       [ [ NS_MAIN, NS_TALK ], [ NS_FILE ], [ NS_MAIN, NS_TALK ] ],
-                       [ [ NS_MAIN, NS_FILE ], [ NS_FILE ], [ NS_MAIN ] ],
-                       // NS_MAIN namespace is always forced
-                       [ [], [ NS_FILE ], [ NS_MAIN ] ]
-               ];
-       }
-
-}
diff --git a/tests/phpunit/includes/specials/SpecialUncategorizedCategoriesTest.php b/tests/phpunit/includes/specials/SpecialUncategorizedCategoriesTest.php
new file mode 100644 (file)
index 0000000..daccd27
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Tests for Special:UncategorizedCategories
+ */
+class SpecialUncategorizedCategoriesTest extends MediaWikiTestCase {
+       /**
+        * @dataProvider provideTestGetQueryInfoData
+        * @covers SpecialUncategorizedCategories::getQueryInfo
+        */
+       public function testGetQueryInfo( $msgContent, $expected ) {
+               $msg = new RawMessage( $msgContent );
+               $mockContext = $this->getMockBuilder( RequestContext::class )->getMock();
+               $mockContext->method( 'msg' )->willReturn( $msg );
+               $special = new SpecialUncategorizedCategories();
+               $special->setContext( $mockContext );
+               $this->assertEquals( [
+                       'tables' => [
+                               0 => 'page',
+                               1 => 'categorylinks',
+                       ],
+                       'fields' => [
+                               'namespace' => 'page_namespace',
+                               'title' => 'page_title',
+                               'value' => 'page_title',
+                       ],
+                       'conds' => [
+                               0 => 'cl_from IS NULL',
+                               'page_namespace' => 14,
+                               'page_is_redirect' => 0,
+                       ] + $expected,
+                       'join_conds' => [
+                               'categorylinks' => [
+                                       0 => 'LEFT JOIN',
+                                       1 => 'cl_from = page_id',
+                               ],
+                       ],
+               ], $special->getQueryInfo() );
+       }
+
+       public function provideTestGetQueryInfoData() {
+               return [
+                       [
+                               "* Stubs\n* Test\n* *\n* * test123",
+                               [ 1 => "page_title not in ( 'Stubs','Test','*','*_test123' )" ]
+                       ],
+                       [
+                               "Stubs\n* Test\n* *\n* * test123",
+                               [ 1 => "page_title not in ( 'Test','*','*_test123' )" ]
+                       ],
+                       [
+                               "* StubsTest\n* *\n* * test123",
+                               [ 1 => "page_title not in ( 'StubsTest','*','*_test123' )" ]
+                       ],
+                       [ "", [] ],
+                       [ "\n\n\n", [] ],
+                       [ "\n", [] ],
+                       [ "Test\n*Test2", [ 1 => "page_title not in ( 'Test2' )" ] ],
+                       [ "Test", [] ],
+                       [ "*Test\nTest2", [ 1 => "page_title not in ( 'Test' )" ] ],
+                       [ "Test\nTest2", [] ],
+               ];
+       }
+}
diff --git a/tests/phpunit/includes/specials/UncategorizedCategoriesPageTest.php b/tests/phpunit/includes/specials/UncategorizedCategoriesPageTest.php
deleted file mode 100644 (file)
index 80bd365..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-<?php
-/**
- * Tests for Special:Uncategorizedcategories
- */
-class UncategorizedCategoriesPageTest extends MediaWikiTestCase {
-       /**
-        * @dataProvider provideTestGetQueryInfoData
-        * @covers UncategorizedCategoriesPage::getQueryInfo
-        */
-       public function testGetQueryInfo( $msgContent, $expected ) {
-               $msg = new RawMessage( $msgContent );
-               $mockContext = $this->getMockBuilder( RequestContext::class )->getMock();
-               $mockContext->method( 'msg' )->willReturn( $msg );
-               $special = new UncategorizedCategoriesPage();
-               $special->setContext( $mockContext );
-               $this->assertEquals( [
-                       'tables' => [
-                               0 => 'page',
-                               1 => 'categorylinks',
-                       ],
-                       'fields' => [
-                               'namespace' => 'page_namespace',
-                               'title' => 'page_title',
-                               'value' => 'page_title',
-                       ],
-                       'conds' => [
-                               0 => 'cl_from IS NULL',
-                               'page_namespace' => 14,
-                               'page_is_redirect' => 0,
-                       ] + $expected,
-                       'join_conds' => [
-                               'categorylinks' => [
-                                       0 => 'LEFT JOIN',
-                                       1 => 'cl_from = page_id',
-                               ],
-                       ],
-               ], $special->getQueryInfo() );
-       }
-
-       public function provideTestGetQueryInfoData() {
-               return [
-                       [
-                               "* Stubs\n* Test\n* *\n* * test123",
-                               [ 1 => "page_title not in ( 'Stubs','Test','*','*_test123' )" ]
-                       ],
-                       [
-                               "Stubs\n* Test\n* *\n* * test123",
-                               [ 1 => "page_title not in ( 'Test','*','*_test123' )" ]
-                       ],
-                       [
-                               "* StubsTest\n* *\n* * test123",
-                               [ 1 => "page_title not in ( 'StubsTest','*','*_test123' )" ]
-                       ],
-                       [ "", [] ],
-                       [ "\n\n\n", [] ],
-                       [ "\n", [] ],
-                       [ "Test\n*Test2", [ 1 => "page_title not in ( 'Test2' )" ] ],
-                       [ "Test", [] ],
-                       [ "*Test\nTest2", [ 1 => "page_title not in ( 'Test' )" ] ],
-                       [ "Test\nTest2", [] ],
-               ];
-       }
-}
index e38d77b..0e46744 100644 (file)
@@ -1,6 +1,7 @@
 <?php
 
 use MediaWiki\Block\DatabaseBlock;
+use MediaWiki\MediaWikiServices;
 
 /**
  * @covers LocalIdLookup
@@ -47,12 +48,12 @@ class LocalIdLookupTest extends MediaWikiTestCase {
 
        public function testLookupCentralIds() {
                $lookup = new LocalIdLookup();
-
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
                $user1 = $this->getLookupUser();
                $user2 = User::newFromName( 'UTLocalIdLookup2' );
 
-               $this->assertTrue( $user1->isAllowed( 'hideuser' ), 'sanity check' );
-               $this->assertFalse( $user2->isAllowed( 'hideuser' ), 'sanity check' );
+               $this->assertTrue( $permissionManager->userHasRight( $user1, 'hideuser' ), 'sanity check' );
+               $this->assertFalse( $permissionManager->userHasRight( $user2, 'hideuser' ), 'sanity check' );
 
                $this->assertSame( [], $lookup->lookupCentralIds( [] ) );
 
@@ -76,11 +77,12 @@ class LocalIdLookupTest extends MediaWikiTestCase {
 
        public function testLookupUserNames() {
                $lookup = new LocalIdLookup();
+               $permissionManager = MediaWikiServices::getInstance()->getPermissionManager();
                $user1 = $this->getLookupUser();
                $user2 = User::newFromName( 'UTLocalIdLookup2' );
 
-               $this->assertTrue( $user1->isAllowed( 'hideuser' ), 'sanity check' );
-               $this->assertFalse( $user2->isAllowed( 'hideuser' ), 'sanity check' );
+               $this->assertTrue( $permissionManager->userHasRight( $user1, 'hideuser' ), 'sanity check' );
+               $this->assertFalse( $permissionManager->userHasRight( $user2, 'hideuser' ), 'sanity check' );
 
                $this->assertSame( [], $lookup->lookupUserNames( [] ) );
 
index b0c0fec..4a7aa05 100644 (file)
@@ -4,6 +4,7 @@ use MediaWiki\Auth\AuthManager;
 use MediaWiki\Block\DatabaseBlock;
 use MediaWiki\Block\CompositeBlock;
 use MediaWiki\Block\SystemBlock;
+use MediaWiki\Permissions\PermissionManager;
 
 /**
  * @covers PasswordReset
@@ -30,16 +31,19 @@ class PasswordResetTest extends MediaWikiTestCase {
                $user->expects( $this->any() )->method( 'getName' )->willReturn( 'Foo' );
                $user->expects( $this->any() )->method( 'getBlock' )->willReturn( $block );
                $user->expects( $this->any() )->method( 'getGlobalBlock' )->willReturn( $globalBlock );
-               $user->expects( $this->any() )->method( 'isAllowed' )
-                       ->will( $this->returnCallback( function ( $perm ) use ( $canEditPrivate ) {
-                               if ( $perm === 'editmyprivateinfo' ) {
-                                       return $canEditPrivate;
-                               } else {
-                                       $this->fail( 'Unexpected permission check' );
-                               }
-                       } ) );
 
-               $passwordReset = new PasswordReset( $config, $authManager );
+               $permissionManager = $this->getMockBuilder( PermissionManager::class )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $permissionManager->method( 'userHasRight' )
+                       ->with( $user, 'editmyprivateinfo' )
+                       ->willReturn( $canEditPrivate );
+
+               $passwordReset = new PasswordReset(
+                       $config,
+                       $authManager,
+                       $permissionManager
+               );
 
                $this->assertSame( $isAllowed, $passwordReset->isAllowed( $user )->isGood() );
        }
@@ -204,9 +208,16 @@ class PasswordResetTest extends MediaWikiTestCase {
                $request->setIP( '1.2.3.4' );
                $performingUser = $this->getMockBuilder( User::class )->getMock();
                $performingUser->expects( $this->any() )->method( 'getRequest' )->willReturn( $request );
-               $performingUser->expects( $this->any() )->method( 'isAllowed' )->willReturn( true );
                $performingUser->expects( $this->any() )->method( 'getName' )->willReturn( 'Performer' );
 
+               $permissionManager = $this->getMockBuilder( PermissionManager::class )
+                       ->disableOriginalConstructor()
+                       ->getMock();
+               $permissionManager->expects( $this->once() )
+                       ->method( 'userHasRight' )
+                       ->with( $performingUser, 'editmyprivateinfo' )
+                       ->willReturn( true );
+
                $targetUser1 = $this->getMockBuilder( User::class )->getMock();
                $targetUser2 = $this->getMockBuilder( User::class )->getMock();
                $targetUser1->expects( $this->any() )->method( 'getName' )->willReturn( 'User1' );
@@ -217,7 +228,8 @@ class PasswordResetTest extends MediaWikiTestCase {
                $targetUser2->expects( $this->any() )->method( 'getEmail' )->willReturn( 'foo@bar.baz' );
 
                $passwordReset = $this->getMockBuilder( PasswordReset::class )
-                       ->setMethods( [ 'getUsersByEmail' ] )->setConstructorArgs( [ $config, $authManager ] )
+                       ->setConstructorArgs( [ $config, $authManager, $permissionManager ] )
+                       ->setMethods( [ 'getUsersByEmail' ] )
                        ->getMock();
                $passwordReset->expects( $this->any() )->method( 'getUsersByEmail' )->with( 'foo@bar.baz' )
                        ->willReturn( [ $targetUser1, $targetUser2 ] );
index 4862747..6f57578 100644 (file)
@@ -1,5 +1,7 @@
 <?php
 
+use MediaWiki\MediaWikiServices;
+
 /**
  * @group Database
  */
@@ -61,7 +63,9 @@ class UserGroupMembershipTest extends MediaWikiTestCase {
                $user->clearInstanceCache();
                $this->assertContains( 'unittesters', $user->getGroups() );
                $this->assertArrayHasKey( 'unittesters', $user->getGroupMemberships() );
-               $this->assertTrue( $user->isAllowed( 'runtest' ) );
+               $this->assertTrue( MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $user, 'runtest' ) );
 
                // try updating without allowUpdate. Should fail
                $ugm = new UserGroupMembership( $user->getId(), 'unittesters', $this->expiryTime );
@@ -72,7 +76,9 @@ class UserGroupMembershipTest extends MediaWikiTestCase {
                $user->clearInstanceCache();
                $this->assertContains( 'unittesters', $user->getGroups() );
                $this->assertArrayHasKey( 'unittesters', $user->getGroupMemberships() );
-               $this->assertTrue( $user->isAllowed( 'runtest' ) );
+               $this->assertTrue( MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $user, 'runtest' ) );
 
                // try removing the group
                $ugm->delete();
@@ -81,7 +87,9 @@ class UserGroupMembershipTest extends MediaWikiTestCase {
                        $this->logicalNot( $this->contains( 'unittesters' ) ) );
                $this->assertThat( $user->getGroupMemberships(),
                        $this->logicalNot( $this->arrayHasKey( 'unittesters' ) ) );
-               $this->assertFalse( $user->isAllowed( 'runtest' ) );
+               $this->assertFalse( MediaWikiServices::getInstance()
+                       ->getPermissionManager()
+                       ->userHasRight( $user, 'runtest' ) );
 
                // check that the user group is now in user_former_groups
                $this->assertContains( 'unittesters', $user->getFormerGroups() );
index 2d87c78..2a4ba4b 100644 (file)
@@ -31,7 +31,6 @@ class UserTest extends MediaWikiTestCase {
                $this->setMwGlobals( [
                        'wgGroupPermissions' => [],
                        'wgRevokePermissions' => [],
-                       'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
                ] );
 
                $this->setUpPermissionGlobals();
@@ -1075,83 +1074,6 @@ class UserTest extends MediaWikiTestCase {
                        'User::newFromActorId works for an anonymous user' );
        }
 
-       /**
-        * Actor tests with SCHEMA_COMPAT_READ_OLD
-        *
-        * The only thing different from testActorId() is the behavior if the actor
-        * row doesn't exist in the DB, since with SCHEMA_COMPAT_READ_NEW that
-        * situation can't happen. But we copy all the other tests too just for good measure.
-        *
-        * @covers User::newFromActorId
-        */
-       public function testActorId_old() {
-               $this->setMwGlobals( [
-                       'wgActorTableSchemaMigrationStage' => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
-               ] );
-
-               $domain = MediaWikiServices::getInstance()->getDBLoadBalancer()->getLocalDomainID();
-               $this->hideDeprecated( 'User::selectFields' );
-
-               // Newly-created user has an actor ID
-               $user = User::createNew( 'UserTestActorIdOld1' );
-               $id = $user->getId();
-               $this->assertTrue( $user->getActorId() > 0, 'User::createNew sets an actor ID' );
-
-               $user = User::newFromName( 'UserTestActorIdOld2' );
-               $user->addToDatabase();
-               $this->assertTrue( $user->getActorId() > 0, 'User::addToDatabase sets an actor ID' );
-
-               $user = User::newFromName( 'UserTestActorIdOld1' );
-               $this->assertTrue( $user->getActorId() > 0, 'Actor ID can be retrieved for user loaded by name' );
-
-               $user = User::newFromId( $id );
-               $this->assertTrue( $user->getActorId() > 0, 'Actor ID can be retrieved for user loaded by ID' );
-
-               $user2 = User::newFromActorId( $user->getActorId() );
-               $this->assertEquals( $user->getId(), $user2->getId(),
-                       'User::newFromActorId works for an existing user' );
-
-               $row = $this->db->selectRow( 'user', User::selectFields(), [ 'user_id' => $id ], __METHOD__ );
-               $user = User::newFromRow( $row );
-               $this->assertTrue( $user->getActorId() > 0,
-                       'Actor ID can be retrieved for user loaded with User::selectFields()' );
-
-               $this->db->delete( 'actor', [ 'actor_user' => $id ], __METHOD__ );
-               User::purge( $domain, $id );
-               // Because WANObjectCache->delete() stupidly doesn't delete from the process cache.
-
-               MediaWikiServices::getInstance()->getMainWANObjectCache()->clearProcessCache();
-
-               $user = User::newFromId( $id );
-               $this->assertFalse( $user->getActorId() > 0, 'No Actor ID by default if none in database' );
-               $this->assertTrue( $user->getActorId( $this->db ) > 0, 'Actor ID can be created if none in db' );
-
-               $user->setName( 'UserTestActorIdOld4-renamed' );
-               $user->saveSettings();
-               $this->assertEquals(
-                       $user->getName(),
-                       $this->db->selectField(
-                               'actor', 'actor_name', [ 'actor_id' => $user->getActorId() ], __METHOD__
-                       ),
-                       'User::saveSettings updates actor table for name change'
-               );
-
-               // For sanity
-               $ip = '192.168.12.34';
-               $this->db->delete( 'actor', [ 'actor_name' => $ip ], __METHOD__ );
-
-               $user = User::newFromName( $ip, false );
-               $this->assertFalse( $user->getActorId() > 0, 'Anonymous user has no actor ID by default' );
-               $this->assertTrue( $user->getActorId( $this->db ) > 0,
-                       'Actor ID can be created for an anonymous user' );
-
-               $user = User::newFromName( $ip, false );
-               $this->assertTrue( $user->getActorId() > 0, 'Actor ID can be loaded for an anonymous user' );
-               $user2 = User::newFromActorId( $user->getActorId() );
-               $this->assertEquals( $user->getName(), $user2->getName(),
-                       'User::newFromActorId works for an anonymous user' );
-       }
-
        /**
         * @covers User::newFromAnyId
         */
@@ -1566,10 +1488,6 @@ class UserTest extends MediaWikiTestCase {
                // logged in users should be inmune to cookie block of type ip/range
                $this->assertNull( $user->getBlock() );
 
-               // cookie is being cleared
-               $cookies = $request->response()->getCookies();
-               $this->assertEquals( '', $cookies['wikiBlockID']['value'] );
-
                // clean up
                $block->delete();
        }
index 22b5938..edb7618 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 
 /**
-* @covers MWDoxygenFilter
+ * @covers MWDoxygenFilter
  */
 class MWDoxygenFilterTest extends \PHPUnit\Framework\TestCase {
 
index b8d1383..cd0d7a5 100644 (file)
@@ -37,7 +37,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $logs[] = [
                        'log_type' => 'patrol',
                        'log_action' => 'patrol',
-                       'log_user' => 7251,
+                       'log_actor' => 7251,
                        'log_params' => '',
                        'log_timestamp' => $dbw->timestamp( '20041223210426' ),
                        'log_namespace' => NS_MAIN,
@@ -49,7 +49,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $logs[] = [
                        'log_type' => 'patrol',
                        'log_action' => 'autopatrol',
-                       'log_user' => 7252,
+                       'log_actor' => 7252,
                        'log_params' => '',
                        'log_timestamp' => $dbw->timestamp( '20051223210426' ),
                        'log_namespace' => NS_MAIN,
@@ -61,7 +61,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $logs[] = [
                        'log_type' => 'block',
                        'log_action' => 'block',
-                       'log_user' => 7253,
+                       'log_actor' => 7253,
                        'log_params' => '',
                        'log_timestamp' => $dbw->timestamp( '20061223210426' ),
                        'log_namespace' => NS_MAIN,
@@ -73,7 +73,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $logs[] = [
                        'log_type' => 'patrol',
                        'log_action' => 'patrol',
-                       'log_user' => 7253,
+                       'log_actor' => 7253,
                        'log_params' => 'nanana',
                        'log_timestamp' => $dbw->timestamp( '20061223210426' ),
                        'log_namespace' => NS_MAIN,
@@ -85,7 +85,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $logs[] = [
                        'log_type' => 'patrol',
                        'log_action' => 'autopatrol',
-                       'log_user' => 7254,
+                       'log_actor' => 7254,
                        'log_params' => '',
                        'log_timestamp' => $dbw->timestamp( '20071223210426' ),
                        'log_namespace' => NS_MAIN,
@@ -97,7 +97,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $logs[] = [
                        'log_type' => 'patrol',
                        'log_action' => 'patrol',
-                       'log_user' => 7255,
+                       'log_actor' => 7255,
                        'log_params' => serialize( [ '6::auto' => true ] ),
                        'log_timestamp' => $dbw->timestamp( '20081223210426' ),
                        'log_namespace' => NS_MAIN,
@@ -109,7 +109,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $logs[] = [
                        'log_type' => 'patrol',
                        'log_action' => 'patrol',
-                       'log_user' => 7256,
+                       'log_actor' => 7256,
                        'log_params' => serialize( [ '6::auto' => false ] ),
                        'log_timestamp' => $dbw->timestamp( '20091223210426' ),
                        'log_namespace' => NS_MAIN,
@@ -121,7 +121,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $logs[] = [
                        'log_type' => 'patrol',
                        'log_action' => 'patrol',
-                       'log_user' => 7257,
+                       'log_actor' => 7257,
                        'log_params' => "9227851\n0\n1",
                        'log_timestamp' => $dbw->timestamp( '20081223210426' ),
                        'log_namespace' => NS_MAIN,
@@ -133,7 +133,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $logs[] = [
                        'log_type' => 'patrol',
                        'log_action' => 'patrol',
-                       'log_user' => 7258,
+                       'log_actor' => 7258,
                        'log_params' => "9227851\n0\n0",
                        'log_timestamp' => $dbw->timestamp( '20091223210426' ),
                        'log_namespace' => NS_MAIN,
@@ -149,47 +149,47 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                        (object)[
                                'log_type' => 'patrol',
                                'log_action' => 'patrol',
-                               'log_user' => '7251',
+                               'log_actor' => '7251',
                        ],
                        (object)[
                                'log_type' => 'patrol',
                                'log_action' => 'autopatrol',
-                               'log_user' => '7252',
+                               'log_actor' => '7252',
                        ],
                        (object)[
                                'log_type' => 'block',
                                'log_action' => 'block',
-                               'log_user' => '7253',
+                               'log_actor' => '7253',
                        ],
                        (object)[
                                'log_type' => 'patrol',
                                'log_action' => 'patrol',
-                               'log_user' => '7253',
+                               'log_actor' => '7253',
                        ],
                        (object)[
                                'log_type' => 'patrol',
                                'log_action' => 'autopatrol',
-                               'log_user' => '7254',
+                               'log_actor' => '7254',
                        ],
                        (object)[
                                'log_type' => 'patrol',
                                'log_action' => 'patrol',
-                               'log_user' => '7255',
+                               'log_actor' => '7255',
                        ],
                        (object)[
                                'log_type' => 'patrol',
                                'log_action' => 'patrol',
-                               'log_user' => '7256',
+                               'log_actor' => '7256',
                        ],
                        (object)[
                                'log_type' => 'patrol',
                                'log_action' => 'patrol',
-                               'log_user' => '7257',
+                               'log_actor' => '7257',
                        ],
                        (object)[
                                'log_type' => 'patrol',
                                'log_action' => 'patrol',
-                               'log_user' => '7258',
+                               'log_actor' => '7258',
                        ],
                ];
 
@@ -266,7 +266,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
 
                $remainingLogs = wfGetDB( DB_REPLICA )->select(
                        [ 'logging' ],
-                       [ 'log_type', 'log_action', 'log_user' ],
+                       [ 'log_type', 'log_action', 'log_actor' ],
                        [],
                        __METHOD__,
                        [ 'ORDER BY' => 'log_id' ]
@@ -288,7 +288,7 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
 
                $remainingLogs = wfGetDB( DB_REPLICA )->select(
                        [ 'logging' ],
-                       [ 'log_type', 'log_action', 'log_user' ],
+                       [ 'log_type', 'log_action', 'log_actor' ],
                        [],
                        __METHOD__,
                        [ 'ORDER BY' => 'log_id' ]
@@ -297,12 +297,12 @@ class DeleteAutoPatrolLogsTest extends MaintenanceBaseTestCase {
                $deleted = [
                        'log_type' => 'patrol',
                        'log_action' => 'autopatrol',
-                       'log_user' => '7254',
+                       'log_actor' => '7254',
                ];
                $notDeleted = [
                        'log_type' => 'patrol',
                        'log_action' => 'autopatrol',
-                       'log_user' => '7252',
+                       'log_actor' => '7252',
                ];
 
                $remainingLogs = array_map(
index cab6c3b..a3a165f 100644 (file)
@@ -102,7 +102,6 @@ return [
                ],
                'dependencies' => [
                        'jquery.color',
-                       'jquery.colorUtil',
                        'jquery.getAttrs',
                        'jquery.highlightText',
                        'jquery.lengthLimit',
index 541c610..22a3a4b 100644 (file)
                return api.post( {} );
        } );
 
+       QUnit.test( 'origin is not included in same-origin GET requests', function ( assert ) {
+               var apiUrl = location.protocol + '//' + location.host + '/w/api.php',
+                       api = new mw.ForeignApi( apiUrl );
+
+               this.server.respond( function ( request ) {
+                       assert.strictEqual( request.url.match( /origin=.*?(?:&|$)/ ), null, 'origin is not included in GET requests' );
+                       request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
+               } );
+
+               return api.get( {} );
+       } );
+
+       QUnit.test( 'origin is not included in same-origin POST requests', function ( assert ) {
+               var apiUrl = location.protocol + '//' + location.host + '/w/api.php',
+                       api = new mw.ForeignApi( apiUrl );
+
+               this.server.respond( function ( request ) {
+                       assert.strictEqual( request.requestBody.match( /origin=.*?(?:&|$)/ ), null, 'origin is not included in POST request body' );
+                       assert.strictEqual( request.url.match( /origin=.*?(?:&|$)/ ), null, 'origin is not included in POST request URL, either' );
+                       request.respond( 200, { 'Content-Type': 'application/json' }, '[]' );
+               } );
+
+               return api.post( {} );
+       } );
+
 }() );
index 4f61abd..a05b50b 100644 (file)
 
                assert.strictEqual( mw.util.escapeRegExp( normal ), normal, 'Alphanumerals are left alone' );
        } );
+
+       QUnit.test( 'debounce', function ( assert ) {
+               var fn,
+                       q = [],
+                       done = assert.async();
+
+               fn = mw.util.debounce( 0, function ( data ) {
+                       q.push( data );
+               } );
+
+               fn( 1 );
+               fn( 2 );
+               fn( 3 );
+
+               setTimeout( function () {
+                       assert.deepEqual(
+                               q,
+                               [ 3 ],
+                               'Last one ran'
+                       );
+                       done();
+               } );
+       } );
 }() );
index f425d87..5be1ed0 100644 (file)
--- a/thumb.php
+++ b/thumb.php
@@ -25,6 +25,7 @@ use MediaWiki\Logger\LoggerFactory;
 use MediaWiki\MediaWikiServices;
 
 define( 'MW_NO_OUTPUT_COMPRESSION', 1 );
+define( 'MW_ENTRY_POINT', 'thumb' );
 require __DIR__ . '/includes/WebStart.php';
 
 // Don't use fancy MIME detection, just check the file extension for jpg/gif/png
index e2b165b..4e6bbd9 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 define( 'THUMB_HANDLER', true );
+define( 'MW_ENTRY_POINT', 'thumb_handler' );
 
 // Execute thumb.php, having set THUMB_HANDLER so that
 // it knows to extract params from a thumbnail file URL.